当前位置: 首页 > 知识库问答 >
问题:

Tomcat 6.0.28在浸泡测试期间由于线程阻塞而无响应

东方和惬
2023-03-14

我们对运行在Tomcat 6.0.28和OpenJDK运行时环境(IcedTea6 1.11.11)上的JavaEE Web应用程序的新版本进行了几次浸泡测试。问题发生在Web层。

一段时间后——第一次50分钟,第二次1小时,第三次2.5小时——集群Web层中的一个随机Tomcat停止响应。查看线程转储,我们看到大量线程突然阻塞。

当问题发生时,线程数从93增加到437。437个线程中的341个在WebappClassLoader上被阻止,如下所示:

"TP-Processor400" daemon prio=10 tid=0x00007f1ee432e800 nid=0x44d9 waiting for monitor entry [0x00007f1ec47c5000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java)
        - waiting to lock <0x00000006f561a758> (a org.apache.catalina.loader.WebappClassLoader)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1329)

一个线程持有锁:

"TP-Processor53" daemon prio=10 tid=0x00007f1ee406f800 nid=0x7cbf runnable [0x00007f1f4545b000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.ClassLoader.findLoadedClass0(Native Method)
        at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:923)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1386)
        - locked <0x00000006f561a758> (a org.apache.catalina.loader.WebappClassLoader)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1329)

一分钟间隔内的后续线程转储表明锁正在被释放,然后由其他线程获得。2分钟后,所有被阻止的线程都被解除阻止,服务器再次正常运行。

Tomcat bug tracker报告了WebappClassLoader的死锁问题,应用程序使用自己的类加载器(https://issues.apache.org/bugzilla/show_bug.cgi?id=48694,是https://issues.apache.org/bugzilla/show_bug.cgi?的翻版id=48903),对我们来说也是如此:我们的应用程序嵌入在一个集群化的OpenCMS安装中,该安装使用org . open CMS . ocee . base . cmsrelaodingclass loader来加载类。

当发生阻塞时,我们还看到CPU时间的GC活动从10%增加到50%,即使内存和堆在那个时候没有增加。

问题是,这种阻塞可能是由什么引起的,我们能做些什么来解决它?

共有1个答案

辛承志
2023-03-14

显然,死锁的原因和修复都在错误本身的注释中。查看https://bz.apache.org/bugzilla/show_bug.cgi?id=48694的评论

 类似资料:
  • 这是一个非阻塞的解决方案,但看起来并不那么优雅。它能以某种方式改进/简化吗?

  • 背景我使用log4j2(2.12.1)与同步根和异步记录器。Lmax环形缓冲区大小默认为256*1024。我在控制台的appender。我用JSON布局记录MapMessage。我的日志消息的平均大小约为100字节。 有了上面的细节,我注意到很少有线程被阻塞在 我的问题是。。 环形缓冲区是否很快就满了,这导致主线程背压(在我的例子中,servlet容器线程是http-nio-8080-exec-1

  • 在Java中,线程可以有不同的状态: 新建、可运行、阻止、等待、定时等待、终止 但是,当线程被IO阻塞时,其状态为“RUNNABLE”。我如何判断它是否被IO阻止?

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 我决定在Java上重写我的Web应用程序(以前是在Python上)。在我的应用程序中,我使用无阻塞I/O,我有工作池(Celery Eventlet线程),我在其中传递由数百个API调用组成的任务。 现在我正在使用Spring WebFlux,但我不明白如何创建一个工作人员池来将我的任务传递到该池,并在获得结果并进行一些计算之后。 (我知道创建ThreadPoolTaskExecutor的可能性,

  • 我们希望建立一个工作流程,其中包含以下步骤,在这个顺序 执行一些同步活动。 通过kafka事件触发外部操作。 收听kafka事件以获取操作结果。 根据结果执行一些其他活动。 Kafka可能包含与工作流无关的事件,因此我们需要一个单独的工作流来过滤该特定工作流的事件。 使用cadence,我计划将它分成两个工作流程 < li >工作流程1 : 1 - 是否可以在不实际阻塞线程的情况下等待 workf