Отладка дампа потока с сервера Java Grpc? - PullRequest
0 голосов
/ 20 октября 2019

Я отлаживаю проблему на сервере Java Grpc, где каждые n минут сервер останавливается при обработке запросов. Я подключил профилировщик, и я сразу вижу проблему, каждые n минут наблюдается скачок числа потоков, а затем через несколько секунд он снова возвращается к нормальному состоянию, и все хорошо в течение следующих n минут. Я взял дамп потока в jvm, когда произошел всплеск потока, и я легко вижу, что есть множество ожидающих потоков. Но оттуда я не могу точно сказать, что вызывает это - см. Пример вывода из дампа потока ниже. Возможно, сервер просто перегружен слишком большим количеством запросов, но я не могу объяснить это снизу:

"grpc-default-executor-1212" - Thread t@4520
   java.lang.Thread.State: TIMED_WAITING
    at java.base@11.0.1/jdk.internal.misc.Unsafe.park(Native Method)
    - parking to wait for <44b4dca3> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.base@11.0.1/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:234)
    at java.base@11.0.1/java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:462)
    at java.base@11.0.1/java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:361)
    at java.base@11.0.1/java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:937)
    at java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1053)
    at java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1114)
    at java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base@11.0.1/java.lang.Thread.run(Thread.java:834)

   Locked ownable synchronizers:
    - None

Кто-нибудь сталкивался с вышеуказанным и могут ли они объяснить причину? (Использование процессора и куча в порядке, поэтому они не вызывают проблемы) Спасибо

Ответы [ 2 ]

0 голосов
/ 23 октября 2019

grpc-java по умолчанию использует Executors.newCachedThreadPool() для обратных вызовов. Кэшированный пул потоков немедленно создает новые потоки, если поток недоступен, вместо постановки задачи в очередь. Реализация представляет собой ThreadPoolExecutor, который позволяет потокам выходить, когда они не используются (ищите «Keep-alive times» в его документах ).

Что, вероятно, происходит, это взрыв работыэто приводит к созданию новых потоков. Затем наступает период низкой активности, который позволяет многим потокам остановиться. Executors.newCachedThreadPool() использует одну минуту keepAliveTime .

Это не объясняет, откуда идет взрыв. Вы можете попробовать указать собственного исполнителя с помощью ServerBuilder.executor() для отладки или просто указать пул потоков фиксированного размера. Вы можете использовать Executors.newFixedThreadPool() или ForkJoinPool. Команда grpc-java рекомендует указывать ваш собственный фиксированный размер executor(), когда это возможно. Но для этого необходимо знать потребности потоков вашего собственного приложения.

0 голосов
/ 20 октября 2019

вы можете получить java doc из SynchronousQueue

Очередь блокировки, в которой каждая операция вставки должна ожидать соответствующей операции удаления другим потоком, и наоборот. Синхронная очередь не имеет внутренней емкости, даже емкости одной

. Вы можете использовать SynchronousQueue в качестве параметра для создания ThreadPool.SynchronousQueue - это очередь без емкости, когда потоки изThreadpool, чтобы получить некоторые задачи, они блокируются, пока некоторые задачи не отправлены.

...