【问题标题】:Tomcat Thread Dump - Possible Stuck ThreadTomcat 线程转储 - 可能卡住的线程
【发布时间】:2014-08-09 21:52:29
【问题描述】:

我在运行 Tomcat 的生产服务器上运行了三个线程转储,间隔 10 秒。我发现相同的线程(相同的线程 ID)出现在所有三个线程转储中,并且正在做完全相同的事情 - 处理 JSP 页面。这是否意味着它被卡住了?或者可能是Tomcat线程池中的同一个线程一遍又一遍地被分配相同的任务。

这是一个中等大小的应用程序,有很多 servlet/JSP 页面、业务逻辑和一个数据库。此外,它相当繁忙(每秒大约 20 个请求)。 Tomcat 独立运行(不落后于 Apache)。

编辑 1(附加信息):主页通常需要不到 10 秒的时间来呈现,因此这不能是对主页的典型单个请求。

编辑 2:几个小时后我又进行了一次线程转储(但没有重新启动 Tomcat),这个特定的线程正在做其他事情。这是否最终意味着线程没有卡住?

这是该特定线程的线程转储部分(仅列出一个,因为其他两个完全相同):

"http-bio-8080-exec-220" daemon prio=10 tid=0x00007f5c801de800 nid=0x3151 runnable [0x00007f5c74d28000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
    at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
    at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
    at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366)
    at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:240)
    at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:119)
    at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:192)
    at org.apache.coyote.Response.doWrite(Response.java:517)
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:408)
    at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
    at org.apache.catalina.connector.OutputBuffer.realWriteChars(OutputBuffer.java:487)
    at org.apache.tomcat.util.buf.CharChunk.append(CharChunk.java:312)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:528)
    at org.apache.catalina.connector.CoyoteWriter.write(CoyoteWriter.java:152)
    at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:119)
    at org.apache.jasper.runtime.JspWriterImpl.write(JspWriterImpl.java:336)
    at java.io.Writer.write(Writer.java:157)
    at org.apache.jasper.runtime.JspWriterImpl.print(JspWriterImpl.java:473)
    at org.apache.taglibs.standard.tag.common.core.UrlSupport.doEndTag(UrlSupport.java:127)
    at org.apache.jsp.WEB_002dINF.jsp.site.home_jsp._jspx_meth_c_005furl_005f22(home_jsp.java:1172)
    at org.apache.jsp.WEB_002dINF.jsp.site.home_jsp._jspx_meth_c_005fif_005f2(home_jsp.java:1141)
    at org.apache.jsp.WEB_002dINF.jsp.site.home_jsp._jspx_meth_c_005fforEach_005f1(home_jsp.java:1102)
    at org.apache.jsp.WEB_002dINF.jsp.site.home_jsp._jspService(home_jsp.java:308)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
    at inspirasites.servlets.HomeServlet.doGet(HomeServlet.java:102)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at inspirasites.filters.CharEncodingFilter.doFilter(CharEncodingFilter.java:23)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at inspirasites.filters.SiteFilter.doFilter(SiteFilter.java:45)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    - locked <0x00000000e12fb330> (a org.apache.tomcat.util.net.SocketWrapper)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

【问题讨论】:

  • 是的,它可能被卡住或者同一个线程执行同一个任务(Tomcat 尽可能地重用线程)。 HTTP BIO 是一种阻塞类型的连接器,因此大部分时间将花在读取或(在这种情况下)写入套接字上。写入套接字没有超时,如果接收器在处理接收到的字节时真的很慢(例如交换),线程可能会被卡住(直到连接关闭或丢失)。但是对于每秒 3 个和 20 个请求的样本,重复使用的线程执行相同任务的可能性不大。
  • @vanOekel 首先,您应该将此作为答案,因为它非常有用。另外,我有一个后续问题:假设线程被卡住,那么在重新启动 Tomcat 之前的所有线程转储仍然会显示它执行相同的任务,对吗?换句话说,Tomcat 永远不会杀死一个卡住的线程。如果是这样,我现在可以进行另一个线程转储,看看它是否仍然存在 :)
  • 我不愿给出答案:有人可能以前见过这种行为并且知道发生了什么(“不太可能”并不是真正的答案)。 Tomcat 不会杀死这样的线程,但我希望在某个时间出现警告/错误日志(“连接重置”或类似的东西)。除了线程转储,您还可以查看打开的连接(“netstat”) - 您应该看到相同的“远程 IP:端口”出现(尽管这也不是决定性的 - 套接字连接通常在请求之间重用(“ HTTP 保持活动状态"))。

标签: java tomcat


【解决方案1】:

我最近在我们的应用程序中看到了完全相同的行为,并且能够重现它。它可能是由发送请求但不使用响应数据的行为不端的客户端引起的。在这种情况下,套接字将阻塞,请参阅此问题的答案:Is an OutputStream in Java blocking? (Sockets)

【讨论】:

    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    相关资源
    最近更新 更多