http://www.linuxeye.com/Linux/2781.html
Tomcat報 Jul 21, 2015 8:45:23 AM org.apache.tomcat.util.net.JIoEndpoint$Acceptor runSEVERE: Socket accept failedjava.net.SocketException: Too many open filesat java.net.PlainSocketImpl.socketAccept(Native Method)at java.net.AbstractPlainSoc
Jul 21, 2015 8:45:23 AM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run SEVERE: Socket accept failed java.net.SocketException: Too many open files at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398) at java.net.ServerSocket.implAccept(ServerSocket.java:530) at java.net.ServerSocket.accept(ServerSocket.java:498) at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60) at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:216) at java.lang.Thread.run(Thread.java:745) 解決的思路:一眼異常立刻想到ulimit,於是使用 ulimit -a 查看Linux內核允許的最大資源 open files (-n) 1024 需要調大限制 ulimit -n 65535 經過觀察,問題依舊...通過 lsof|grep tomcat|wc -l 看到tomcat的io居然有1082個,立馬想到了nginx與tomcat的不協調造成的,據網絡資料顯示:tomcat端默認開啟了 keepalive,而nginx把連接交給了tomcat並不關系是否關閉,因此tomcat需要等待"connectionTimeout"設置的超 時時間來關閉,所以最好設置“maxKeepAliveRequests”為1,讓每個連接只相應一次就關閉,這樣就不會等待timeout了。因此設置 tomcat: <Connector port="8080" protocol="HTTP/1.1" maxKeepAliveRequests="1" connectionTimeout="20000" URIEncoding="UTF-8" redirectPort="8443" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" maxKeepAliveRequests="1" connectionTimeout="20000" redirectPort="8443" /> 重啟tomcat,觀察,問題依舊!翻頁查看lsof lsof|grep tomcat|more 發現有大量的memcached的IO,因此把問題定位在memcached上,為了方便觀察,新建memcached實例,發現memcached的IO數量逐步增加,最終導致tomcat崩潰! 嗨,終於找到問題了 ^O^ 通過code review,發現每次調用memcached的API,都會new一個XMemcachedClient(一個memcached客戶端),每次new的時候都會設置一個尺寸的連接池,而連接是預建立的,因此導致memcached的IO數目劇增。 問題終於解決了,memcached的IO數目穩定了,tomcat也運行良好。。。 不經意間,發現memcached的IO數目以連接池的尺寸在遞增,心里一落千丈,拔涼拔涼的,貌似還是沒解決! 查看tomcat的日志,發現了端倪: Jul 21, 2015 3:06:40 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: The web application [/MobileService] appears to have started a thread named [Xmemcached-Reactor-0] but has failed to stop it. This is very likely to create a memory leak. 原來在每次重新部署webapp時,tomcat殺不掉XmemcachedClient的連接進程,由於使用的是spring,所以需要在memcachedClient的bean里增加"destroy-method"。OK,到此為止tomcat的IO以及memcached的IO都穩定了,並在合理范圍之內,tomcat的是160左右。 為了擔心“maxKeepAliveRequests”的設置對tomcat的性能有影響,暫時刪除了“ maxKeepAliveRequests”,需要對tomcat的整體性能優化進行了解才去配置。 小插曲:由於使用了spring框架的監聽配置Log4j,如果下面的順序顛倒了會造成不能寫日志的問題 <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 經過一天的推理、懷疑、實驗、否定,終於搞定,又過了一次"福爾摩斯"的偵探癮,作此標記,留給后來人!今天發現打開的IO仍然在增加,雖然幅度比較少,但最高也達到了960+,因此需要優化Tomcat配置,增加線程池,並配置keepAliveTimeout和maxKeepAliveRequests <Executor name="mobileThreadPool" namePrefix="catalina-exec-" maxThreads="600" minSpareThreads="20" maxIdleTime="60000" /> <Connector executor="mobileThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" keepAliveTimeout="15000" maxKeepAliveRequests="1" URIEncoding="UTF-8" redirectPort="8443" /> 今天使用壓力測試,依然出現“Too many open files”,使用ulimit發現“open files (-n)”仍然是1024,那么之前設置的65535是沒起作用,而切換到root用戶發現卻是65535;而在非root用戶下 ulimit -n 65535 會報異常: ulimit: max user processes: cannot modify limit 原來是被 /etc/security/limits.conf 限制了,打開此文件即可看到,對默認用戶是有限制的,因此可以加入 * soft noproc 65535 * hard noproc 65535 * soft nofile 65535 * hard nofile 65535 這樣就非root用戶就可以設置ulimit為65535了。 設置了ulimit后,我在root下啟動tomcat,壓力還會容易出現“Too many open files”,但其實使用“lsof -u root|wc -l”並不多,才3000+;root后來我單獨建立了個用戶來啟動,暫時沒出現問題。 PS: /proc/sys/fs/file-max表示kernel中維護的最大文件描述符數目。不管這個系統上有多少了用戶登錄,有多少個進程在運行,所有打開的文件數目總合都不能超過這個數字。 /etc/security/limit.conf用來設置每個用戶最多可以打開的文件數目。 普通用戶可以通過ulimit -n 命令來設置hard limit(只能改小) 和soft limit(可以改大和改小). 把上面的內容概括成3條就是:
轉載請保留固定鏈接: http://www.linuxeye.com/Linux/2781.html |