2012-11-11 46 views
26

已經問過類似的問題,但刪除了它,因爲我認爲我修復了它,但我錯了。Play框架/ Netty不釋放套接字

我使用播放框架在生產我的web項目之一。不時播放不呈現主頁或不返回某些靜態內容文件。

第一張截圖顯示螢火控制檯,該網站的加載服務主頁時,在開始stucked。 enter image description here 當2個靜態資源未加載時,第二個屏幕截圖顯示fiddler控制檯。

enter image description here

最初的應用程序運行正常,它有5-7天的工作,我可以看到這個問題。它很難重現,它發生在15次之一,我不得不刪除緩存數據並重新加載頁面。 (在FF中按CRTL-F5)。問題可以在不同機器和操作系統的大多數瀏覽器中重現。最初,我認爲託管服務提供商存在一些問題。但是我改變了它,問題沒有消失。

該劇的版本是1.2.5。也嘗試了1.2.2。 Play在CentOS-5-32位上作爲獨立服務器運行。

我懷疑,有一些問題Netty這是由遊戲框架使用。 Play使用Netty 3.5.7 final jar。

cd /proc/28761/fd 
ls -l | wc -l 
337 

已打開的文件描述符的數量從140增加到350.注意,在開始和之後的平均網站負載是相同的。

我可以看到很多的進程打開插座,這是不是以後發佈的。

lrwx------ 1 root root 64 Nov 11 10:34 300 -> socket:[1079566] 
lrwx------ 1 root root 64 Nov 11 10:34 301 -> socket:[1079568] 
lrwx------ 1 root root 64 Nov 11 10:34 302 -> socket:[1149958] 
lrwx------ 1 root root 64 Nov 11 10:34 303 -> socket:[1160807] 
lrwx------ 1 root root 64 Nov 11 10:34 304 -> socket:[1160605] 
lrwx------ 1 root root 64 Nov 11 10:34 305 -> socket:[1157435] 
lrwx------ 1 root root 64 Nov 11 10:34 306 -> socket:[1160607] 
lrwx------ 1 root root 64 Nov 11 10:34 307 -> socket:[1160609] 
lrwx------ 1 root root 64 Nov 11 10:34 308 -> socket:[1155542] 
lrwx------ 1 root root 64 Nov 11 10:34 309 -> socket:[1120231] 

更新

應用的開始打開的TCP連接數(正在運行的幾個小時)爲63

Total: 150 (kernel 181) 
TCP: 63 (estab 38, closed 5, orphaned 0, synrecv 0, timewait 3/0), ports 44 

Transport Total  IP  IPv6 
*   181  -   - 
RAW  0   0   0 
UDP  7   4   3 
TCP  58  9   49 
INET  65  13  52 
FRAG  0   0   0 

2天之後的運行,一些開放的TCP連接490

[[email protected] fd]# ss -s 
Total: 459 (kernel 490) 
TCP: 378 (estab 271, closed 23, orphaned 0, synrecv 0, timewait 9/0), ports 37 

Transport Total  IP  IPv6 
*   490  -   - 
RAW  0   0   0 
UDP  7   4   3 
TCP  355  12  343 
INET  362  16  346 
FRAG  0   0   0 

所有這一切都打開ŧ CP連接是http連接(不是數據庫或任何其他)。網站上的平均負載始終相同,但打開的文件描述符和打開的套接字數量一直在增加,直到too many open files exception

最初,應用程序以9-15個新I/O線程(Netty工作者)啓動。所有Netty線程大部分時間都處於運行狀態。並且~16播放處於等待狀態的線程。

後運行的Netty職工人數的幾天成爲27.我不是專家的Netty,不知道這是否是正常的行爲。

幾個線程去僵局:1個播放線程和1個Netty的線程。還有另一個播放線程被第一個播放線程鎖定。所以共有3個鎖定線程。我敢肯定,這個死鎖不是問題的根本原因,但根本原因可以是相同的

Name: New I/O worker #21 
State: BLOCKED on [email protected] owned by: play-thread-2 
Total blocked: 44 Total waited: 9 

Stack trace: 
org.jboss.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:188) 
org.jboss.netty.handler.stream.ChunkedWriteHandler.handleUpstream(ChunkedWriteHandler.java:140) 
org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:792) 
org.jboss.netty.channel.SimpleChannelUpstreamHandler.channelClosed(SimpleChannelUpstreamHandler.java:212) 
org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:93) 
org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:792) 
org.jboss.netty.handler.codec.replay.ReplayingDecoder.cleanup(ReplayingDecoder.java:636) 
org.jboss.netty.handler.codec.replay.ReplayingDecoder.channelClosed(ReplayingDecoder.java:533) 
org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:93) 
org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) 
org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559) 
org.jboss.netty.channel.Channels.fireChannelClosed(Channels.java:476) 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.close(AbstractNioWorker.java:631) 
org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:109) 
org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:66) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:780) 
org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:55) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:785) 
org.jboss.netty.handler.stream.ChunkedWriteHandler.handleDownstream(ChunkedWriteHandler.java:111) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:582) 
org.jboss.netty.channel.Channels.close(Channels.java:821) 
org.jboss.netty.channel.AbstractChannel.close(AbstractChannel.java:194) 
org.jboss.netty.channel.ChannelFutureListener$1.operationComplete(ChannelFutureListener.java:41) 
org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:399) 
org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:385) 
org.jboss.netty.channel.DefaultChannelFuture.setSuccess(DefaultChannelFuture.java:334) 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:493) 
    - locked [email protected] 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromTaskLoop(AbstractNioWorker.java:431) 
org.jboss.netty.channel.socket.nio.AbstractNioChannel$WriteTask.run(AbstractNioChannel.java:364) 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.processWriteTaskQueue(AbstractNioWorker.java:349) 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:245) 
org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38) 
org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) 
org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) 
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
java.lang.Thread.run(Thread.java:662) 

第二個線程:

Name: play-thread-2 
State: BLOCKED on [email protected] owned by: New I/O worker #21 
Total blocked: 23 Total waited: 34 778 

Stack trace: 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:654) 
org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:408) 
org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:127) 
org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:66) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:780) 
org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:63) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591) 
org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:785) 
org.jboss.netty.channel.Channels.write(Channels.java:733) 
org.jboss.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:262) 
    - locked [email protected] 
org.jboss.netty.handler.stream.ChunkedWriteHandler.handleDownstream(ChunkedWriteHandler.java:121) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:591) 
org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:582) 
org.jboss.netty.channel.Channels.write(Channels.java:712) 
org.jboss.netty.channel.Channels.write(Channels.java:679) 
org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245) 
play.server.PlayHandler.serveStatic(PlayHandler.java:886) 
play.server.PlayHandler$NettyInvocation.init(PlayHandler.java:182) 
play.Invoker$Invocation.run(Invoker.java:276) 
play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:229) 
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) 
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
java.util.concurrent.FutureTask.run(FutureTask.java:138) 
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98) 
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206) 
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
java.lang.Thread.run(Thread.java:662) 

更新

我將相同的Play應用程序部署到Tomcat 7的相同環境。通過24小時後問題消失,打開的TCP連接數保持不變。打開的文件描述符的數量不超過〜70。這是相同的生產主機,相同的數據庫和應用程序的相同用戶。

+3

請求是直接打到Play應用程序還是通過代理(Apache等)? –

+0

不使用代理,請求直接播放播放 – Anton

+1

你做了任何線程轉儲在服務器端,也許有什麼東西吊死在服務器上,防止播放重用線程 –

回答

1

我實際上遇到了一個類似的bug,但是在JVM中(運行哪個播放器)。因此,關閉通道指向文件句柄直到通過關閉JVM才被釋放。唉,我不記得我是如何找到錯誤報告的,或者我會鏈接到它,但它是JVM中已知的錯誤。我最終不得不解決它。我可以建議的最好的事情是重寫代碼以儘可能地使用相同的通道/文件句柄。

+0

似乎不太可能,因爲這會影響任何種類的Java Web App,但是我不會遇到任何我們經常看到的問題。 – sorencito

1

ChunkedWriteHandler存在幾個死鎖問題。所有這些似乎都可以在你的Netty版本中得到解決。無論如何,這段代碼似乎正在吸引這類問題。我建議你爲Netty人員提出問題。

https://issues.jboss.org/browse/NETTY-384

另請參閱「類似問題」得到的關於有該類有多少問題是一個想法。