Как найти утечку нити в приложении Spring + Tomcat - PullRequest
0 голосов
/ 18 января 2019

У меня есть веб-приложение с пружинной загрузкой (1.5.2), которое запускается в tomcat (8.5) как единственное веб-приложение. Общее количество потоков в JVM (openjdk 1.8.0_181) монотонно увеличивается почти (хотя и не полностью) с постоянной скоростью, начиная с нескольких сотен в начале до примерно 3000 в неделю. К этому времени большинство трассировок стека потоков выглядят так:

WAITING Thread[pool-917-thread-1,5,main]
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)

Приложение работает нормально, эти потоки, кажется, не занимают слишком много памяти (по крайней мере, по сравнению с десятками гигабайт, которые обычно использует приложение), но их существование указывает на некоторую скрытую утечку внутри приложения. На момент написания этой статьи я не могу найти поток с именем pool-.* в другом состоянии, поэтому я не знаю, что они обычно делают перед тем, как стать зомби. Приложение никогда не будет повторно развернуто без перезапуска Tomcat.

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

1 Ответ

0 голосов
/ 18 января 2019

Наиболее вероятные причины появления потоков таким образом:

  1. Tomcat был неправильно настроен, например, executor maxThreads установлен в необоснованно высокое значение по умолчанию 200.
  2. Код приложения создает пул внешних потоков, например, Executors.newCachedThreadPool(), который испытывает всплеск нити.
  3. Во время повторного развертывания приложения пул потоков, созданный неразвернутым приложением, не останавливается правильно. См. этот ответ .
  4. Код приложения создает потоки с new Thread().

Точка 4 маловероятна, так как ваша трассировка стека показывает java.util.concurrent.ThreadPoolExecutor. Найдите пул, который создает потоки с префиксом pool- (код приложения grep и конфигурация Tomcat для pool-). Затем закройте бассейн.

...