2013-08-29 48 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