我们最近开始在我们的tomcat服务器上看到线程计数的峰值(通常在100左右时达到峰值超过1000)。我们在其中一个tomcat服务器上执行了一个线程转储,而它的线程数很高,发现大量的线程正在等待MultiThreadedHttpConnectionManager $ ConnectionPool,堆栈跟踪如下:
“TP-Processor21700”守护程序prio = 10 tid = 0x4a0b3400 nid = 0x2091 in Object.wait()[0x399f3000..0x399f4004] java.lang.Thread.State:WAITING(在对象监视器上) at java.lang.Object.wait(Native Method) - 等待< 0x58ee5030> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager $ ConnectionPool) 在org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:518) - 已锁定< 0x58ee5030> (a org.apache.commons.httpclient.MultiThreadedHttpConnectionManager $ ConnectionPool) 在org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416) 在org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153) 在org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) 在org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323) ...
我们的代码中有3个点调用httpClient.executeMethod()(通过http请求获取信息到另一个tomcat服务器)。在每种情况下,传递给它的GetMethod对象都已经设置了套接字超时值(即通过getMethod.getParams()。setSoTimeout();),并且在Spring中配置MultiThreadedConnectionManager以使connectionTimeout值为10秒。我注意到的一件事是,3个httpClient.executeMethod()调用中只有2个调用getMethod.releaseConnection(),所以我想知道这是否是问题的原因(即连接没有明确发布)。然而,奇怪的是 问题只是在最近几天才开始发生,而且源代码还没有被修改超过一年,而且最近没有一个请求进入tomcat服务器。在问题开始发生前几天发生的一个变化是我们将tomcat服务器使用的JVM从Java 5(1.5更新14)升级到Java 6(1.6更新25)。我们已经尝试暂时将JVM版本恢复到Java 5,以查看问题是否已停止发生,但事实并非如此。另一点需要注意的是,在大多数情况下,tomcat服务器最终会恢复并且 线程数量恢复正常 - 我们只有一个实例,其中tomcat进程因线程数增加而出现崩溃。
我们正在运行Tomcat 5.5,并在Red Hat Linux环境中运行针对Java 1.6更新25的commons-httpclient-3.1.jar。
如果您能就此问题的原因提出任何建议,请与我们联系。
感谢。
答案 0 :(得分:3)
问题确实是由于3个httpClient.executeMethod(getMethod)调用中只有2个调用了getMethod.releaseConnection()。确保所有3个httpClient.executeMethod(getMethod)调用都在try / catch块中,然后是包含对getMethod.releaseConnection()的调用的finally块,以防止发生高线程计数。虽然这段代码已经在我们的实时系统中存在了一年多,但似乎最近刚开始发生高线程数问题的原因是因为各种搜索引擎爬虫已经开始使用大量URL请求来访问该站点,导致代码所在正在使用连接,但随后没有释放执行。问题解决了。