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.AbstractPlainSocjava
Tomcat報 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了。nginx 設置了ulimit後,我在root下啓動tomcat,壓力還會容易出現「Too many open files」,但其實使用「lsof -u root|wc -l」並很少,才3000+;root後來我單獨創建了個用戶來啓動,暫時沒出現問題。web PS:spring /proc/sys/fs/file-max表示kernel中維護的最大文件描述符數目。無論這個系統上有多少了用戶登陸,有多少個進程在運行,全部打開的文件數目總合都不能超過這個數字。shell /etc/security/limit.conf用來設置每一個用戶最多能夠打開的文件數目。apache 普通用戶能夠經過ulimit -n 命令來設置hard limit(只能改小) 和soft limit(能夠改大和改小).tomcat 把上面的內容歸納成3條就是:性能優化
|