2011-06-12 119 views
9

我在一個網站上運行Jetty,大約100個請求/秒,前面有nginx。我只注意到在日誌中,做了部署和啓動碼頭,是一小會兒它是垃圾郵件後只需要幾分鐘:Jetty IOException:打開的文件太多

java.io.IOException: Too many open files 
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) 
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:163) 
    at org.mortbay.jetty.nio.SelectChannelConnector$1.acceptChannel(SelectChannelConnector.java:75) 
    at org.mortbay.io.nio.SelectorManager$SelectSet.doSelect(SelectorManager.java:673) 
    at org.mortbay.io.nio.SelectorManager.doSelect(SelectorManager.java:192) 
    at org.mortbay.jetty.nio.SelectChannelConnector.accept(SelectChannelConnector.java:124) 
    at org.mortbay.jetty.AbstractConnector$Acceptor.run(AbstractConnector.java:708) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 

對於一兩分鐘。 我做了一個「lsof的-u碼頭」,看見數百行:

java 15892 jetty 1020u IPv6   298105434  0t0  TCP 192.168.1.100:http-alt->192.168.1.100:60839 (ESTABLISHED) 
java 15892 jetty 1021u IPv6   298105438  0t0  TCP 192.168.1.100:http-alt->192.168.1.100:60841 (ESTABLISHED) 
java 15892 jetty 1022u IPv6   298105441  0t0  TCP 192.168.1.100:http-alt->192.168.1.100:60842 (ESTABLISHED) 
java 15892 jetty 1023u IPv6   298105443  0t0  TCP 192.168.1.100:http-alt->192.168.1.100:60843 (ESTABLISHED) 

,其中192.168.1.100是服務器內部IP。

正如你所看到的,這使得打開文件的數量達到默認的最大值1024.我可以增加這個,但我想知道爲什麼會發生這種情況?它在Jetty的nio套接字接受器中,這是由連接請求風暴引起的嗎?

+1

每個套接字都是一個文件,所以每個連接都有一個文件(描述符),即使它正在等待。請求通常會做什麼,需要多長時間?在碼頭上有100個請求/秒,查詢一個本地數據庫服務器需要2秒/請求,你已經有400個「文件」。 – extraneon 2011-06-12 18:00:08

+0

我的大多數請求只需要幾ms,但當應用程序首次啓動時,它們可能需要幾秒鐘,這是我認爲發生的事情。垃圾收集器偶爾還會「停止世界」暫停,這會導致所有請求在短時間內堆積起來,從而導致間歇性地發生。之後我將不得不調整GC,同時我剛剛增加了限制。 – 2011-06-12 18:43:23

+1

我在Tomcat6中不時得到類似的東西,最初以爲這是操作系統扔它的玩具。也只是增加了作爲臨時解決方案的限制。 – 2011-06-12 19:04:12

回答

11

儘管Jetty中可能存在一個錯誤,但我認爲更可能的解釋是您的打開文件限制太低。通常,1024默認值對於中等使用的Web服務器來說是不夠的。

測試此方法的一個好方法是使用apache bench來模擬您所看到的入站流量。在遠程主機上運行此命令將產生超過10個併發連接的1000個請求。

ab -c 10 -n 1000 [http://]hostname[:port]/path 

現在用netstat算你的Web服務器上的插座...

netstat -a | grep -c 192.168.1.100 

希望你會發現什麼是你的插座會在某個值不顯着大於1024(我的是高原在16384)。

確保連接在您的業務邏輯中正常關閉的另一件好事。

netstat -a | grep -c CLOSE_WAIT 

如果你看到這個數字繼續在你的應用程序的生命週期成長,你可能會丟失到的Connection.close打了幾個電話()。

+0

此外,如果Full GC顯然真的佔用了太多時間,請查看Java的ConcurrentMarkSweep收集器。 – jpredham 2011-06-13 15:49:11