一.问题描述
在tomcat上,压力测试(并行50,串行100,即5000次)的JAVA程序B44。
压测完毕后(压测试程序已执行完,tomcat也没有任何程序再跑)tomcat就假死了(访问tomcat没反应,无法显示该页)。
然后,再过两分钟,tomcat又能正常访问了,一切自动恢复正常。
二.分析问题
先后进行了多次测试,发现以下问题:
1.与写日志的线程无关。因为,改成了线程池也结果相同。
2.与写日志无关。因为,不写日志也结果相同。
3.与程序无关,我写了个最简单的JSP,压测也是这样。
4.与程序的运行时间有关,如果这个程序要运行好几百毫秒,反而不会假死。
5.用APACHE分发到多个TOMCAT,则会产生APACHE假死,而TOMCAT不会假死。如果有硬件负载均衡器分发到多个TOMCAT,估计也会产生与APACHE分发相同的结果。
6.与运行的web server无关。因为,在weblogic上运行也结果相同。
7.与内存无关,因为压测的过程中,内存变化不大。
8.与机器性能无关,先后在多次性能不同的机器上进行了测试,效果都相同。
9.与web server分配的堆栈大小无关,改大后反而报内存不足。
10.最后,发现非常关键的一点,假死时除了用IE访问地址报“无法打开该网页”外, 压测的程序都抛出同一例外信息“java.net.BindException: Address already in use: connect”。
所以,得出大概原因是:短时间内new socket操作很多,而socket.close()操作并不能立即释放绑定的端口,而是把端口设置为TIME_WAIT状态,过段时间(默认240s)才释放,(用netstat -na看到有好几千行被调用的端口为TIME_WAIT),最后系统资源耗尽(windows上是耗尽了pool of ephemeral ports,这段区间在1024-5000之间)。
三.解决办法
1.调高web服务器的最大连接线程数,即打开tomcat的server.xml文件,设置 Connector的以下参数:minProcessors="70" maxProcessors="2000" acceptCount="2000"
2.修改运行web服务器的机器的操作系统网络配置,即在注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters中增加以下两个DWORD参数:
MaxUserPort=fffe
TcpTimedWaitDelay=1e
最后,重新启动计算机。TcpTimedWaitDelay和MaxUserPort的参数作用详见TcpTimedWaitDelay和MaxUserPort作用及设置。