2013-08-29 45 views
13

我们最近将Jetty服务器从版本6.1.25升级到9.0.4。它们部署在Windows 2008服务器上的Java 1.7.0_11 64位上。码头9挂起,QueuedThreadPool增长较大

除了为Jetty(start.ini - 非常好)所需的配置更改以外,我们保留了所有JVM标志与以前相同。在生产环境中部署6天后,服务器无法响应HTTP请求。内部“心跳”处理在此期间继续按常规运行,但未处理外部请求。该服务已重新启动,6天后又再次无响应。

在我的初步审查中,我以为我是与https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318东西。但是,该JVM问题已从Java 1.8_0XX回迁到Java 1.7.0_06。这让我回顾了线程处理。

认为它可能与日食网站上的情况400617/410550有关,虽然它本身并不像书面文字那样呈现,并且该案例在Jetty 9.0.3中已被明显解决。

通过JMX监视应用程序显示“qtp”线程的线程数量随着时间的推移而持续增长,并且我一直未能成功搜索解决方案。主题配置也是目前的设置:

threads.min=10 
threads.max=200 
threads.timeout=60000 

所有QTP线程通常与以下堆栈跟踪等待状态:

Name: qtp1805176801-285 
State: WAITING on [email protected] 
Total blocked: 0 Total waited: 110 

Stack trace: 
sun.misc.Unsafe.park(Native Method) 
java.util.concurrent.locks.LockSupport.park(Unknown Source) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source) 
java.util.concurrent.Semaphore.acquire(Unknown Source) 
org.eclipse.jetty.util.BlockingCallback.block(BlockingCallback.java:96) 
org.eclipse.jetty.server.HttpConnection$Input.blockForContent(HttpConnection.java:457) 
org.eclipse.jetty.server.HttpInput.consumeAll(HttpInput.java:282) 
    - locked [email protected] 
org.eclipse.jetty.server.HttpConnection.completed(HttpConnection.java:360) 
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:340) 
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:224) 
org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358) 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601) 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532) 
java.lang.Thread.run(Unknown Source) 

仔细一看后,这似乎从有最新的线程不同以下状态:

Name: qtp1805176801-734 
State: TIMED_WAITING on java.u[email protected]77b83b6e 
Total blocked: 5 Total waited: 478 

Stack trace: 
sun.misc.Unsafe.park(Native Method) 
java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source) 
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source) 
org.eclipse.jetty.util.BlockingArrayQueue.poll(BlockingArrayQueue.java:390) 
org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:509) 
org.eclipse.jetty.util.thread.QueuedThreadPool.access$700(QueuedThreadPool.java:48) 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:563) 
java.lang.Thread.run(Unknown Source) 

根据命名规则,一些QTP线程是很老(qtp1805176801-206),而有些是很新(qtp18051768 01-6973)。我觉得有趣的是,旧的线程不会基于60秒的空闲超时而超时。应用服务在美国营业时间为客户提供服务,并且在清晨几小时大部分时间都处于闲置状态,届时我预计几乎所有的游泳池都将被清理干净。

希望有人能够指出我如何跟踪这个问题的正确方向。我对Jetty的使用经验让我相信他们的东西非常扎实,大多数问题都是在我们的实现(已存在)或JVM相关(已完成)中编程的。如果你认为我可能会在线索上追逐一条红鲱鱼,也欢迎提供建议。

新信息: 跟踪异常远一点,这似乎在GWT RPC调用超时,同时等待响应引起的。以下堆栈跟踪显示与处于无效状态的线程相关的日志文件中的异常。使用它来检查和查找Jetty/GWT交互问题的其他报告。

2013-09-03 08:41:49.249:WARN:/webapp:qtp488328684-414: Exception while dispatching incoming RPC call 
java.io.IOException: java.util.concurrent.TimeoutException: Idle timeout expired: 30015/30000 ms 
    at org.eclipse.jetty.util.BlockingCallback.block(BlockingCallback.java:103) 
    at org.eclipse.jetty.server.HttpConnection$Input.blockForContent(HttpConnection.java:457) 
    at org.eclipse.jetty.server.HttpInput.read(HttpInput.java:130) 
    at java.io.InputStream.read(Unknown Source) 
    at com.google.gwt.user.server.rpc.RPCServletUtils.readContent(RPCServletUtils.java:175) 
    at com.google.gwt.user.server.rpc.RPCServletUtils.readContentAsGwtRpc(RPCServletUtils.java:205) 
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.readContent(AbstractRemoteServiceServlet.java:182) 
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:239) 
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) 
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:698) 
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1506) 
    at c.t.b.servlet.PipelineFilter.doFilter(PipelineFilter.java:56) 
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494) 
    at c.v.servlet.SetRequestEncoding.doFilter(SetRequestEncoding.java:27) 
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494) 
    at c.t.b.servlet.OutOfMemoryFilter.doFilter(OutOfMemoryFilter.java:39) 
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1486) 
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:503) 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138) 
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564) 
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213) 
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1094) 
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:432) 
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175) 
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1028) 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136) 
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:258) 
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109) 
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) 
    at org.eclipse.jetty.server.Server.handle(Server.java:445) 
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:267) 
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:224) 
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: 
java.util.concurrent.TimeoutException: Idle timeout expired: 30015/30000 ms 
    at org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:153) 
    at org.eclipse.jetty.io.IdleTimeout$1.run(IdleTimeout.java:50) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
+0

我在码头9.2发现这个问题(见:如何防止Linux Mint的一致的Java暂停模式](http://stackoverflow.com/questions/25338802))。 jVisualVM显示38小时运行后HttpConnector线程泄漏的开始。大约10个线程保持活动状态,下一个连接启动另一个线程集群以进行下一次HTTP读取。 – will

回答

1

QueuedThreadPool是一个共享的线程池。其中的线程将被重新用于其他处理。是的,追踪线程池,假设线程将被清理,是一个红色的鲱鱼。那些线程会在很长一段时间内慢慢地从池中落下(想想几个小时)。这是线程池中的一个性能决定(创建较为昂贵,尽可能不频繁地执行)。

至于你粘贴的堆栈跟踪,它的不完整,所以对行为的猜测量非常高。但是,话虽如此,这两行可以表示正常的操作,但没有堆栈跟踪的其余部分几乎没有继续下去。

另外,您使用的Java版本1.7.0_06和1.7.0_11都很旧,而且您需要修复数百个错误。

+0

Joakim - 我已经更新了堆栈跟踪以显示完整的堆栈跟踪。随着我仔细观察,最新的线程通常处于以下状态: – skimbleton

+0

我们计划在几周内将JDK版本升级到1.7.0_25(最新的Java 7稳定版本),虽然对发布说明不会产生太多的结果,表明发生了重大变化。 – skimbleton

6

结束在Eclipse/Jetty网站上发布该问题。以下链接可用于追踪对解决方案的任何永久修复。

https://bugs.eclipse.org/bugs/show_bug.cgi?id=416477

问题与对请求作为GWT RPC调用的一部分期间已经超时一个QTP线程的信号量锁定做。原始请求会计时,超时时间为30秒。请求在等待Semaphore.acquire方法完成时超时。作为清理请求的一部分,HTTPConnection会尝试对请求发送.consumeAll,并再次尝试一次Sempahore.acquire。这一次,请求没有定时,并且锁定保持原位,直到线程中断。

该问题似乎是非常具体的平台,因为Jetty未能重现该问题,我无法找到任何其他问题的报告。此外,这只发生在我们的一个生产环境中。我的猜测是,GWT RPC Code,Jetty和操作系统之间正在发生一些事情。我们计划为JDK,Jetty和GWT SDK进行小规模升级。

解决方法 最初的解决方法是每天通过JMX控制台每天多次中断锁定的线程。我们的长期解决方案是构建一个清理机制,查找这些锁定的线程并在其上调用中断方法。

+0

移至:https://bugs.eclipse.org/bugs/show_bug.cgi?id = 435322 – cquezel

1

我和Jetty 9.2.3.v20140905和Java(build 1.8.0_20-b26)64位一样。

解决方法。安装的monit http://mmonit.com/monit/

# monit.conf 
check process jetty-service with pidfile "/opt/jetty-service/jetty.pid" 
start program = "/usr/sbin/service jetty-service start" with timeout 30 seconds 
stop program = "/usr/sbin/service jetty-service stop" 
if totalmem is greater than 1268 MB for 10 cycles then restart 
if 5 restarts within 5 cycles then timeout