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条就是:性能优化
|