【问题标题】:How to locate thread leak in spring + tomcat applicationspring+tomcat应用中如何定位线程泄漏
【发布时间】:2019-06-12 14:09:43
【问题描述】:

我有一个 Spring Boot (1.5.2) Web 应用程序,它作为唯一的 Web 应用程序在 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)

应用程序工作正常,这些线程似乎并没有占用太多内存(至少与应用程序通常消耗的数十 GB 相比),但它们的存在表明应用程序内部存在一些隐藏的泄漏。在写这篇文章时,我目前找不到一个名为pool-.* 的线程处于不同的状态,所以我不知道他们在变成僵尸之前通常会做什么。如果不重新启动 tomcat,则永远不会重新部署应用程序。

我的问题是是否有人遇到过类似的事情以及他们是如何解决的,如果没有,我如何诊断为什么这些线程被创建而不是之后被删除。

【问题讨论】:

  • 所以你的意思是说所有线程都在等待并且没有关闭。如果这是 tomcat 的问题,那么您现在很容易发现,无论如何确实提到了您正在使用的 tomcat 版本。如果是,您是否在应用程序中的任何地方设置执行器。我建议检查该代码或使用将 ThreadFactory 作为输入的构造函数。覆盖工厂中的 newThread 方法以使用自定义名称。如果它是您的应用程序,那么使用线程名称您可以轻松找出错误代码并处理该特定部分。
  • 好的,它是一个工作线程池。线程名称是什么?
  • @AndyBrown 线程名称:pool-[0-9]*-thread-1,5,main

标签: java spring tomcat threadpool


【解决方案1】:

以这种方式产生线程的最可能原因:

  1. Tomcat 配置错误,例如executor maxThreads 从默认值 200 设置为不合理的高值。
  2. 应用程序代码创建一个 ubound 线程池,例如Executors.newCachedThreadPool() 遇到线程峰值。
  3. 在应用程序重新部署期间,由未部署的应用程序创建的线程池未正确停止。见this answer。
  4. 应用程序代码使用new Thread() 创建线程。

第 4 点不太可能,因为您的堆栈跟踪显示 java.util.concurrent.ThreadPoolExecutor。找到创建带有前缀pool- 的线程的池(grep 应用程序代码和pool- 的Tomcat 配置)。然后盖上游泳池。

【讨论】:

  • 第 1 点不太可能。 Tomcat 使用它自己的 TaskQueue 类扩展 LinkedBlockingQueue 并覆盖 take()。 TaskQueue.take() 将出现在堆栈跟踪中。
  • 第3点不太可能,我们总是在重新部署之前重启tomcat。我将编辑问题以添加更多信息。
  • 第 1 点也不太可能,因为它们应该以 catalina-exec- 开头,如 server.xml 所述:<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 哦,抱歉,它已被注释掉,所以可能是这样。
猜你喜欢
  • 2014-10-30
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 2012-04-02
  • 2017-05-06
  • 2017-02-15
  • 1970-01-01
相关资源
最近更新 更多