防止MongoDB出现“state should be: open”错误导致宕机

8
我正在使用monger库在一个多线程的clojure应用中使用mongodb,但我的其中一个生产者线程出现了问题。
java.lang.IllegalStateException: state should be: open
 at com.mongodb.assertions.Assertions.isTrue (Assertions.java:70)
    com.mongodb.connection.DefaultServer.getConnection (DefaultServer.java:84)
    com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection (ClusterBinding.java:86)
    com.mongodb.operation.QueryBatchCursor.getMore (QueryBatchCursor.java:205)
    com.mongodb.operation.QueryBatchCursor.hasNext (QueryBatchCursor.java:103)
    com.mongodb.MongoBatchCursorAdapter.hasNext (MongoBatchCursorAdapter.java:46)
    com.mongodb.DBCursor.hasNext (DBCursor.java:155)
    clojure.lang.RT$4.invoke (RT.java:512)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.RT.seq (RT.java:525)
    clojure.core$seq__6416.invokeStatic (core.clj:137)
    clojure.core$map$fn__6875.invoke (core.clj:2719)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.RT.seq (RT.java:525)
    clojure.core$seq__6416.invokeStatic (core.clj:137)
    clojure.core$map$fn__6875.invoke (core.clj:2719)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.RT.seq (RT.java:525)
    clojure.core$seq__6416.invokeStatic (core.clj:137)
    clojure.core$filter$fn__6902.invoke (core.clj:2782)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.ChunkedCons.chunkedNext (ChunkedCons.java:59)
    clojure.lang.ChunkedCons.next (ChunkedCons.java:43)
    clojure.lang.RT.next (RT.java:703)
    clojure.core$next__6400.invokeStatic (core.clj:64)
    clojure.core$dorun.invokeStatic (core.clj:3115)
    clojure.core$doall.invokeStatic (core.clj:3121)
    clojure.core$doall.invoke (core.clj:3121)
    myapp.ns1.$somefn.invokeStatic (ns1.clj:93)
    myapp.ns1.$somefn.invoke (ns1.clj:90)
    myapp.ns1$anotherfn.invokeStatic (ns1.clj:124)
    myapp.ns1$anotherfn.invoke (ns1.clj:116)
    myapp.ns2$doit.invokeStatic (ns2:21)
    myapp.ns2$doit.invoke (ns2:17)
    myapp.ns2$producer$fn__11200.invoke (ns2:45)
    myapp.ns2$producer.invokeStatic (ns2:31)
    myapp.ns2$producer.invoke (ns2:25)
    myapp.ns2$_start$fn__11230.invoke (ns2:70)
    clojure.core$binding_conveyor_fn$fn__6766.invoke (core.clj:2020)
    clojure.lang.AFn.call (AFn.java:18)
    java.util.concurrent.FutureTask.run (FutureTask.java:266)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617)
    java.lang.Thread.run (Thread.java:745)

我发现了很多其他人遇到的相同问题,他们都通过删除某些conn.close()调用来解决问题。
我只创建一个连接,并且唯一调用close的地方是在关闭时。Java驱动程序管理线程池,因此我不确定我们正在谈论哪个连接。查询返回的DbObject是否有自己专用的连接,并且正是这个连接死掉了?
我尝试通过指定:socket-keep-alive true并将:socket-timeout显式设置为0(默认值为无限制)来修复它,但没有效果。
在monger中,有一些with-open的用法,我想这可能会导致我遇到的问题。以防db对象与此处传递的某个连接相关联,被关闭了,我尝试删除所有db对象的重用,但没有效果。
另一个想法是with-open可能与其中的lazy stuff交互不良,但将所有内容包装在doall中使其变得急切也没有任何效果。
我正在运行一个副本集,并且在从mongodb上运行ReadPreference/secondary。您有什么其他想法可能是出了问题?

堆栈跟踪可能有助于解决问题。 - evanchooly
1个回答

2

在我的应用程序中,经过一番努力排除了懒惰的因素后,异常信息变成了"DB游标未找到"。此时很明显出了问题,通过使用notimeout管理自己的游标,而不是使用monger,随机错误得到了解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接