来自MarkLogic Java客户端API的HTTP连接进入死锁



经过一些压力测试,我们基于Java的中间件通过Java客户端API访问MarkLogic服务器,我在无法打开更多HTTP连接并出现死锁的情况下运行。我使用一个DatabaseClient共享实例,但在每个请求上创建一个JSONDocumentManager(使用一个用于读取的JacksonHandle,不处理特定的关闭问题)。可能存在连接未正确关闭的问题,还是我必须自己关心?

通过查看无法处理更多连接的netstat,我确实在FIN_WAIT_2:中看到了109个到MarkLogic服务器(运行在localhost:8040上)的连接

ffffff8045f765a0 31c91c01 tcp4       0      0  localhost.8040     localhost.65396    FIN_WAIT_2 

以及CLOSE_WAIT:中相同数量(109)的TCP连接

ffffff804ff83400 73965e73 tcp4       0      0  localhost.49286    localhost.8040     CLOSE_WAIT

我正在使用MarkLogic服务器7.0.4和Java 1.7(Mac OSX 10.9.5)以及MarkLogic客户端API 2.0.4。这是线程转储的第一部分(有10个类似的线程似乎在等待服务器响应):

"http-nio-8080-exec-10" #31 daemon prio=5 os_prio=31 tid=0x00007fc61f344000 nid=0x7c03 waiting on condition [0x00000001265bb000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007a59cfff8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.http.impl.conn.tsccm.WaitingThread.await(WaitingThread.java:159)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:398)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:298)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:238)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:423)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:170)
    at com.marklogic.client.impl.DigestChallengeFilter.handle(DigestChallengeFilter.java:34)
    at com.sun.jersey.api.client.filter.HTTPDigestAuthFilter.handle(HTTPDigestAuthFilter.java:493)
    at com.sun.jersey.api.client.Client.handle(Client.java:648)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
    at com.marklogic.client.impl.JerseyServices.getDocumentImpl(JerseyServices.java:612)
    at com.marklogic.client.impl.JerseyServices.getDocument(JerseyServices.java:568)
    at com.marklogic.client.impl.DocumentManagerImpl.read(DocumentManagerImpl.java:270)
    at com.marklogic.client.impl.DocumentManagerImpl.read(DocumentManagerImpl.java:204)
    at com.marklogic.client.impl.DocumentManagerImpl.read(DocumentManagerImpl.java:164)
    at com.acme.dashboard.service.ReportMetadataRepository.getByName(ReportMetadataRepository.java:64)

为了更好的可读性,省略了堆栈跟踪的更多细节。在看了JerseyServices之后,我还试图调整以下系统属性(不幸的是,没有任何改进):

com.marklogic.client.maximumRetrySeconds: 3 (default: 120)
com.marklogic.client.minimumRetries: 3 (default: 8)

听起来您可能遇到了JacksonHandle和TuplesHandle未关闭连接的错误(github问题#89)。此问题已在Java客户端API 2.0.5中修复。您是否能够在ML Server的7.0-5实例上运行测试,并使用Java Client API的2.0.5版本?

FIN_WAIT和CLOSE_WAIT中的套接字可能由于多种原因而出现,包括内核问题(已知)。

我会从开始到结束查看单个连接,以确保它正在关闭套接字,并且服务器也在关闭——如果双方都关闭连接,您应该会很快看到从FIN_WAIT到无的状态转换
一个常见的问题是无法关闭连接的代码路径。你不能指望GC这样做,它最终会完成对象,但通常还不够快。检查以验证您是否正在释放DatabaseClient。你开多久?

我在烹饪书和文档中看到的例子表明,在关闭之前,它的使用时间相当短。

还要检查您的线程数与服务器端口上配置的线程数。如果您发送更多并发请求,则服务器配置为,然后您可以使用单个客户端达到这样的死锁状态。

最新更新