经过一段时间的繁重负载后,Java / jetty不响应连接

我们的Java servlet在Jetty下运行时遇到了一个非常棘手的问题.当负载低至中等时,它可以很好地工作,但是当负载达到一定水平时,它将在大约10-20分钟后停止响应请求.

如果我们在使用curl连接到它时跟踪主java进程,我们可以看到它设置连接,接收请求,解析它并执行它通常做的事情(查询Solr服务器,执行一些MySQL查询等),但是结果永远不会发送回客户端.

当它挂起时,它会无限期地挂起.没有多少时间会使它“突然出现”,但是如果我们杀死主java / jetty进程下的任何随机线程,则线程数会下降并且它会再次开始响应请求.

以下是它的外观:

# curl http://localhost:8080/some-servlet-url

(Does not respond at this point)

# ps -efL | grep qserv | wc -l
243
# ps -efL | grep qserv | wc -l
243
# ps -efL | grep qserv | wc -l
243

(Number of threads remain seemingly constant)

# kill 29760   <--- random thread under the main java/jetty process
# ps -efL | grep qserv | wc -l
26

(Number of threads immediately decreases sharply)

# curl http://localhost:8080/some-servlet-url
... HTTP response ...

(Responds to connections again)

该服务器是运行Ubuntu 12.04.1 LTS和Jetty 8.1.7.v20120910的m2.2xlarge Amazon EC2实例

$java -version
java version "1.7.0_07"
OpenJDK Runtime Environment (IcedTea7 2.3.2) (7u7-2.3.2-1ubuntu0.12.04.1)
OpenJDK 64-Bit Server VM (build 23.2-b09,mixed mode)

我们尝试了几种不同的java和Jetty版本.我们也尝试过使用Tomcat而不是Jetty – 同样的问题.

使用yourkit分析应用程序显示没有明显的线程锁定或过多的cpu使用率.

有任何想法吗?

编辑:我们能够得到挂起的java进程的堆栈跟踪,看起来所有的http线程都处于这种状态:

"http-bio-8080-exec-5" daemon prio=10 tid=0x00007fe518007800 nid=0x1fc5 in Object.wait() [0x00007fe57934f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076ee9d230> (a org.apache.commons.pool.impl.GenericObjectPool)
        at java.lang.Object.wait(Object.java:503)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:810)
        - locked <0x000000076ee9d230> (a org.apache.commons.pool.impl.GenericObjectPool)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:95)
        at net.acmecorp.active.QueryResultXMLFormatter.selectBestHitsAndRunDocumentCompletion(QueryResultXMLFormatter.java:362)
        at net.acmecorp.active.QueryResultXMLFormatter.queryResultToXMLRootElement(QueryResultXMLFormatter.java:167)
        at net.acmecorp.active.QueryPrepareAndExecuter.prepareParametersAndExecuteQuery_AndInvokeFormatter(QueryPrepareAndExecuter.java:239)
        at net.acmecorp.servlets.MultiQueryServlet.handle(MultiQueryServlet.java:470)
        at net.acmecorp.servlets.MultiQueryServlet.doGet(MultiQueryServlet.java:85)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        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.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        - locked <0x0000000700dd70d0> (a org.apache.tomcat.util.net.socketWrapper)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

   Locked ownable synchronizers:
        - <0x000000076ed40990> (a java.util.concurrent.ThreadPoolExecutor$Worker)

我自己并不是一个真正的java人,所以我无法确切地看到这里有什么问题,但看起来他们似乎都在等待……

最佳答案
您有数据库池问题,您的http线程都在等待数据库资源释放.这是一个常见问题,您需要增加池中数据库连接的数量,因此不再是问题,或者您需要使用像jetty中的QoSFilter这样的QoS服务来限制已经进入的请求数量保护小型数据库池的进程.

现在,您的数据库池被消耗的原因可能是许多事情,您可能会在应用程序中泄漏它们(从池中获取它们,使用它们,并且永远不会返回它们),或者您可能只是有太多请求进入同时.或者是数据库池本身的问题,它发生了.

无论哪种方式,这不是jetty或tomcat问题,它是应用程序和数据库间的资源争用问题.请求进入jetty或tomcat,进入servlet域,然后在servlet等中等待数据库连接,就这么简单.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...