【问题标题】:MongoCursorNotFoundException -Query failed with error code -5MongoCursorNotFoundException - 查询失败,错误代码 -5
【发布时间】:2017-04-08 17:10:06
【问题描述】:

我们遇到了以下异常。

com.mongodb.MongoCursorNotFoundException: Query failed with error code -5 and error message 'Cursor 43249415092 not found on server xx.xx.xx.xx:27017' 
        at com.mongodb.connection.GetMoreProtocol.receiveMessage(GetMoreProtocol.java:115)
        at com.mongodb.connection.GetMoreProtocol.execute(GetMoreProtocol.java:68)
        at com.mongodb.connection.GetMoreProtocol.execute(GetMoreProtocol.java:37)
        at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:155)
        at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:219)
        at com.mongodb.connection.DefaultServerConnection.getMore(DefaultServerConnection.java:194)
        at com.mongodb.operation.QueryBatchCursor.getMore(QueryBatchCursor.java:197)
        at com.mongodb.operation.QueryBatchCursor.hasNext(QueryBatchCursor.java:93)
        at com.mongodb.MongoBatchCursorAdapter.hasNext(MongoBatchCursorAdapter.java:46)
        at com.mongodb.DBCursor.hasNext(DBCursor.java:152)

我们无法找到根本原因,因为我们很少遇到此异常。

我们还观察到应用程序无法从光标读取 但没有抛出异常。

在没有抛出异常的情况下,我们取线程转储,发现从mongo读取的线程处于RUNNABLE状态。

java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:152)
        at java.net.SocketInputStream.read(SocketInputStream.java:122)
        at com.mongodb.connection.SocketStream.read(SocketStream.java:85)
        at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:503)
        at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:221)
        at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:102)
        at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:416)
        at com.mongodb.connection.GetMoreProtocol.receiveMessage(GetMoreProtocol.java:112)
        at com.mongodb.connection.GetMoreProtocol.execute(GetMoreProtocol.java:68)
        at com.mongodb.connection.GetMoreProtocol.execute(GetMoreProtocol.java:37)
        at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:155)
        at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:219)
        at com.mongodb.connection.DefaultServerConnection.getMore(DefaultServerConnection.java:194)
        at com.mongodb.operation.QueryBatchCursor.getMore(QueryBatchCursor.java:197)
        at com.mongodb.operation.QueryBatchCursor.hasNext(QueryBatchCursor.java:93)
        at com.mongodb.MongoBatchCursorAdapter.hasNext(MongoBatchCursorAdapter.java:46)
        at com.mongodb.DBCursor.hasNext(DBCursor.java:152)

请帮我找出这个问题的根本原因?

【问题讨论】:

  • 请出示您的代码。
  • 通常,光标会在一段时间后超时。您可以使用 collection.find().noCursorTimeout(true).iterator(); 覆盖它
  • 但是如果光标上的不活动时间大于10分钟(对于java驱动程序),那么只有它超时。但我们的应用程序立即读取
  • OP 说这种异常很少发生。不看代码和它运行的环境,很难缩小根本原因。
  • @notionquest 谢谢。我之前尝试过 noCursorTimeOut 并且它有效。但我想知道为什么线程处于 RUNNABLE 状态。如果读取失败,应该抛出一些错误吧?

标签: java mongodb mongodb-query


【解决方案1】:

最近,我遇到了同样的问题。经过长时间的研究,我想通了。在我的场景中,我有 4 个 mongos,它们位于负载平衡之后(随机返回 mongos IP 地址)。在我的连接字符串中,我使用负载均衡主机作为 mongoDB 集群的地址。

当应用启动时,mongoDB 驱动会创建一个带有连接池的server。在连接池中,有来自 4 个 mongos 的混合连接。

当你查询一个大数据时(比batchSize大),第一批数据来自mongos A,那么当后面的批请求推送时,连接可能连接到mongos B /C 或 D(source code)。他们当然找不到光标。所以,MongoCursorNotFoundException 被抛出。

如何处理?

不要在连接字符串中使用平衡主机。改为使用所有 mongos IP 地址。让mongoDB驱动自己来平衡请求。

错误mongodb://your.load.balance.host:27000/yourDB?connectTimeoutMS=60000&minPoolSize=100&maxPoolSize=100&waitqueuemultiple=20&waitqueuetimeoutms=60000

正确mongodb://10.0.0.1:27017,10.0.0.2:27017,10.0.0.3:27017,10.0.0.4:27017/yourDB?connectTimeoutMS=60000&minPoolSize=100&maxPoolSize=100&waitqueuemultiple=20&waitqueuetimeoutms=60000

有一个更好的解决方案:可以为每个mongos配置一个唯一且专用的主机,然后修改RIGHT连接字符串:用这个主机替换IP地址。

【讨论】:

    猜你喜欢
    • 2018-11-29
    • 2018-09-03
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 2012-03-04
    相关资源
    最近更新 更多