之前使用的是apache-tomcat-7.0.26+jdk1.6.0_31运行很久了,算是正常,因为有时候也会出现close_wait过多问题,大约2-3千吧,然后就自动恢复了。
现在升级版本到apache-tomcat-8.0.9+jdk1.7.0_72运行7-8个小时就要重启,不然就报close_wait超高一万多个,然后就报socket connect timeout,必须重启,时间也不确定就是7-8个小时,有时长点十多个小时,不一定。查看tomcat的catalina.out有大量下面错误:
27-Oct-2015 22:25:33.621 INFO [pool-1300-thread-1] org.apache.coyote.AbstractProcessor.setErrorState An error occurred in processing while on a non-container thread. The connection will be closed immediately
java.io.IOException: APR error: -32
at org.apache.coyote.http11.InternalAprOutputBuffer.writeToSocket(InternalAprOutputBuffer.java:292)
at org.apache.coyote.http11.InternalAprOutputBuffer.writeToSocket(InternalAprOutputBuffer.java:245)
at org.apache.coyote.http11.InternalAprOutputBuffer.flushBuffer(InternalAprOutputBuffer.java:214)
at org.apache.coyote.http11.AbstractOutputBuffer.flush(AbstractOutputBuffer.java:306)
at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:763)
at org.apache.coyote.Response.action(Response.java:177)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:345)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:313)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:110)
at net.bull.javamelody.FilterServletOutputStream.flush(FilterServletOutputStream.java:52)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:297)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.PrintWriter.flush(PrintWriter.java:320)
at com.iyd.commons.bigpipe.Pagelet.writeValue(Pagelet.java:86)
at com.iyd.commons.bigpipe.Pagelet.call(Pagelet.java:78)
at com.iyd.commons.bigpipe.Pagelet.call(Pagelet.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
不知道是不是和版本升级有关系,请各位达人帮忙看看,非常感谢!
首先你要知道 close_wait 是什麼,這個狀態與 time_wait 有一定的相似之處,都會持有這個連線一定的時間不放。我們知道,幾乎所有的作業系統對單一進程的句柄數(連接數)都有限制,例如多數 linux 系統預設是 1024 個。
舉例
某日,你的人品爆發,網站突然來了 1000 個人,那麼 tomcat 將消耗 1000 個連接去處理這些請求
當請求返回後,這 1000 個連接並沒有馬上銷毀,而是全部處於 wait 狀態
這時你的網站又來了1000 個人(人品持續爆發),但之前那1000 個連接是無法接受新的請求的(全部處於wait 狀態),所以你現在只有24 個連接可以使用,so,其他976 人陷入了漫長的等待。 。 。 。
5分鐘後,最初的 1000 個連接被逐漸釋放了,這時你又有 1000 個連接可以使用了
無奈那些陷入等待的976 人已經走的差不多了,就只剩下了3 個,但是值得高興的是,因為有了可用連接,他們都可以愉快的連接到你的網站,快樂的玩耍了
故事講到這裡我想你也明白了是什麼導致的問題,是因為那些處於 wait 的連接太多,導致可用連接應接不暇。
那麼,如何最佳化,答案很簡單,停用 wait ,讓連線在返回後立刻關閉,成為一個可用連線。
以 tomcat 為例
注意 keepAliveTimeout="0" 即為關鍵所在,其他 server 都會有相關配置,有興趣的自己去翻翻文件。
修改系統句柄數限制,並設定係統tcp的逾時