HTTP-соединения из MarkLogic Java Client API зашли в тупик

После некоторого стресс-тестирования нашего промежуточного программного обеспечения на основе Java, обращающегося к серверу MarkLogic через клиентский API Java, я запустил ситуацию, когда больше не может быть открыто HTTP-соединение и возникает ситуация взаимоблокировки. Я использую один DatabaseClient общий экземпляр, но создать JSONDocumentManager на каждый запрос (с JacksonHandle для чтения не обрабатывается конкретное закрытие вопроса). Может ли быть проблема, что соединения не закрыты должным образом, или я должен заботиться сам?

Глядя на netstat в точке, из которой больше не могут быть обработаны соединения, я вижу точно 109 подключений к серверу MarkLogic (работает на localhost:8040) в FIN_WAIT_2:

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

и такое же количество (109) соединений TCP в CLOSE_WAIT:

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

Я использую сервер MarkLogic 7.0.4 с Java 1.7 (Mac OSX 10.9.5) и клиентским API MarkLogic 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)

2 ответа

Решение

Похоже, что вы можете столкнуться с ошибкой, когда JacksonHandle и TuplesHandle не закрывают свои соединения (выпуск github № 89). Это было исправлено в Java Client API 2.0.5. Можете ли вы запустить свои тесты на 7.0-5 экземпляре ML Server и использовать версию 2.0.5 Java Client API?

Сокеты в FIN_WAIT и CLOSE_WAIT могут возникать по многим причинам, включая проблемы с ядром (известны).

Я бы начал смотреть на одно соединение от начала до конца, чтобы убедиться, что оно закрывает сокет и что сервер тоже - вы должны увидеть переход состояния из FIN_WAIT в ничто довольно быстро, если обе стороны закрывают соединение.
Распространенной проблемой являются пути кода, которые не закрывают соединение. Вы не можете рассчитывать на то, что GC сделает это, он в конечном итоге завершит работу с объектами, но часто не достаточно скоро. Проверьте, чтобы убедиться, что вы освобождаете свой DatabaseClient. Как долго вы держите его открытым?

Примеры, которые я вижу в Поваренных книгах и документах, показывают, что он использовался в течение довольно короткого периода времени, прежде чем был закрыт.

Также проверьте количество потоков против количества потоков, настроенных на порту сервера. Если вы отправляете больше параллельных запросов, тогда сервер настроен, и вы можете перейти в тупиковое состояние, например, с помощью одного клиента.

Другие вопросы по тегам