通过 Grails 域标准在活动游标中发现 Mongo CursorNotFound 异常

Posted

技术标签:

【中文标题】通过 Grails 域标准在活动游标中发现 Mongo CursorNotFound 异常【英文标题】:Mongo CursorNotFound exception in active cursor via Grails domain criteria 【发布时间】:2015-06-19 21:35:40 【问题描述】:

我正在使用 Grails 2.4.4、mongo 插件 3.0.2、MongoDB 2.4.10,使用远程数据库连接。

grails 
    mongo 
        host = "11.12.13.14"    // A remote server IP
        port = 27017
        databaseName = "blogger"
        username = "blog"
        password = "xyz"
        options 
            autoConnectRetry = true
            connectTimeout = 3000
            connectionsPerHost = 40
            socketTimeout = 120000
            threadsAllowedToBlockForConnectionMultiplier = 5
            maxAutoConnectRetryTime=5
            maxWaitTime=120000
        
    

在我们应用程序的一部分中,一个服务方法会迭代超过 20,000 个用户并向他们发送电子邮件:

Person.withCriteria        // Line 323
    eq("active", true)
    order("dateJoined", "asc")
.each  personInstance ->
   // Code to send an email which takes an average of 1 second

为一些 6000 个用户执行此操作后,我得到了一个 MongoDB 游标异常:

2015-04-11 07:31:14,218 [quartzScheduler_Worker-1] ERROR listeners.ExceptionPrinterJobListener  - Exception occurred in job: Grails Job
org.quartz.JobExecutionException: com.mongodb.MongoException$CursorNotFound: Cursor 1337814790631604331 not found on server 11.12.13.14:27017 [See nested exception: com.mongodb.MongoException$CursorNotFound: Cursor 1337814790631604331 not found on server 11.12.13.14:27017]
        at grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:111)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: com.mongodb.MongoException$CursorNotFound: Cursor 1337814790631604331 not found on server 11.12.13.14:27017
        at com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:218)
        at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:198)
        at com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:176)
        at com.mongodb.QueryResultIterator.getMore(QueryResultIterator.java:141)
        at com.mongodb.QueryResultIterator.hasNext(QueryResultIterator.java:127)
        at com.mongodb.DBCursor._hasNext(DBCursor.java:551)
        at com.mongodb.DBCursor.hasNext(DBCursor.java:571)
        at org.grails.datastore.mapping.mongo.query.MongoQuery$MongoResultList$1.hasNext(MongoQuery.java:1893)
        at com.test.person.PersonService.sendWeeklyEmail(PersonService.groovy:323)
        at com.test.WeeklyJob.execute(WeeklyJob.groovy:41)
        at grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:104)
        ... 2 more

我查找了文档,发现光标在 20 分钟后自动关闭,当我用日志确认时,这个异常正好在 20 分钟后出现。

但是这种20分钟后自动关闭的行为适用于非活动游标,但这里游标是活动的。

更新

我阅读了一些文章,发现这可能是 TCP keepalive 超时的问题。于是我们把 TCP keepalive 超时时间从默认的 2 小时改成了 2 分钟,但还是没有解决问题。

【问题讨论】:

【参考方案1】:

这台服务器上的 MonoDB 似乎存在兼容性问题。阅读更多关于 Jira 的详细信息https://jira.mongodb.org/browse/SERVER-18439

希望这对其他人有帮助!

【讨论】:

以上是关于通过 Grails 域标准在活动游标中发现 Mongo CursorNotFound 异常的主要内容,如果未能解决你的问题,请参考以下文章

在 Grails 中对域实例进行版本控制以供批准

从域对象调用 Grails 服务是否很糟糕? [关闭]

为啥 Grails 在域对象保存时不通知我错误?

Grails 更新而不是删除

用户中的内存不足错误通过 grails 中的提要导入

在 grails 中获取分离的域实体