问题描述:web前台页面打开很慢,慢的结果是,缓冲了25分钟左右页面打不开,大量close_wait假死等待关闭,导致请求堆积,出现超时错误访问超时报错如图(1)。
图(1)
环境工具:A. 服务器硬件信息
型号 DELL R1670
CPU Intel 四核/颗 X 2颗
内存 16G
硬盘 600G/块 X 4块
存储 Raid5
B. 服务器软件信息
操作系统 CentOS6.3
应用服务器 apache2.2+tomcat6.0
第三方软件 Server Protect for Linux(趋势科技的防病毒软件,在操作系统上安装使用)、Iguard(天存的防篡改软件,在apache上加载使用)、Iwall(天存的防火墙软件,在apache上加载使用)
解决过程:1. 网站的应用服务器apache从2.0升级到2.2后,不知道为什么在apache和tomcat重启一段时间后,就出现访问迟缓问题,如图(1),因为项目上加载了第三方软件,我怀疑是第三方软件和升级后的apache的版本的兼容性问题。所以我请第三方软件厂商,也根据升级后的apache版本更新了iguard和iwall产品。出问题的时候,我还检查了httpd进程的运行情况,如下:
[root@localhost /]#ps -ef|grep httpd|wc -l
152
2. 观察三天左右,还是发生apache和tomcat重启一段时间后,出现访问迟缓问题。我再次检查httpd进程的运行情况如下:
[root@localhost /]#ps -ef|grep httpd|wc -l
152
为什么每次出现访问问题的时候,httpd进程数都是152呢?
于是我检查apache的MPM工作模式,如下:
[root@localhost /]# /cicro/wcm/as/apache/bin/httpd -l
core.c
prefork.c
http_core.c
mod_so.c
证明是prefork.c工作模式,接下来查找apache的httpd.conf配置文件,发现缺少
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
这就印证了为什么httpd进程数达到152的时候,网站访问就特别慢,因为MaxClients是 Apache可以同时处理的请求数上限,是对Apache性能影响最大的参数。如果请求总数已达到这个值(可通过ps -ef|grep httpd|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。对于目前项目的网站,其缺省值150是不够的。于是我增加了
ServerLimit 2000
StartServers 10
MinSpareServers 25
MaxSpareServers 75
MaxClients 1000
ThreadsPerChild 25
MaxRequestsPerChild 10000
3. 配置好httpd.conf以后,我观察到第五天时候,发现网站访问又出问题了,我检查httpd进程的运行情况如下:
[root@localhost /]#ps -ef|grep httpd|wc -l
1002
再次印证了访问问题和httpd进程数、以及httpd.conf的MaxClients有关。个人觉得apache的最大连接数设置成1000对于这个项目来说,足够了。于是在想为什么时间一长,就就积累了这么多没有消亡的httpd进程。
于是我再用netstat -an|grep 80查看服务器的连接,发现列表很大,觉得有点不正常,就去网上了解下,知道apache的性能问题一般都与TIME_WAIT和CLOSE_WAIT有关系。我就用netstat -an|grep httpd|grep TIME_WAIT和netstat -an|grep httpd|grep CLOSE_WAIT分别查看两种状态的httpd连接数目。发现TIME_WAIT的正常,发现大量tcp CLOSE_WAIT假死等待关闭,情况如图(2):
图(2)
4. 图(2)中有大量CLOSE_WAIT状态的127.0.0.1:8009端口和127.0.0.1的连接,8009是apache和tomcat的整合使用端口;我再查看其中一个CLOSE_WAIT状态的连接的进程的连接状况(netstat -an|grep httpd|grep 22399),结果有两个连接,一个是apache和tomcat通信(127.0.0.1:8009端口和127.0.0.1)的CLOSE_WAIT连接,一个是外部用户访问apache的ESTABLISHED连接;我再去查看这个进程具体情况(ps -ef|grep httpd|grep 22399),发现这个进程CPU的占用时间是00:00:00,也就意味着CPU还没空处理它;我再查看这种进程的数目(ps -ef|grep httpd|grep 00:00:00|wc -l),如图(3)
图(3)
5. 竟然有这么多进程都没有被CPU处理,难道是CPU资源不够,我就用top看下CPU资源使用情况,如图(4)
图(4)
发现CPU的资源还有很多的剩余,那为什么这么多进程占用CPU的时间是0呢?
6. 客户等着解决问题,我凭目前的知识量,无法在短期内查到具体原因,只好网上寻求解决问题的方法:
方案一,在tomcat的workers.properties里面配置相关条件
worker.tomcat.lbfactor=50
worker.tomcat.cachesize=10
worker.tomcat.cache_timeout=600
worker.tomcat.socket_keepalive=1
worker.tomcat.socket_timeout=300
方案二,优化服务器内核参数(/etc/sysctl.conf)
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_keepalive_time=1800
net.ipv4.tcp_keepalive_probes=4
net.ipv4.tcp_keepalive_intvl=15
方案三,关闭tomcat的keepalive参数
方案四,做定时任务检查httpd进程数目,一旦发现httpd进程数目异常,就重启apache和tomcat
7.针对于本项目目前的状况,我采用了方案四,编写了linux shell脚本如下:
#!/bin/sh
httpcount=`ps -ef|grep httpd|wc -l`
echo $httpcount
if [ $httpcount -gt 900 ]; then
killall httpd
killall java
/cicro/wcm/bin/startas.sh
echo "Restart successfully because of much useless process."
else
echo "It is OK!"
fi
为了保证白天用户正常上网和用户体验,在每天早上6:30执行脚本,发现异常则重启;观察了几天,发现方案四还是不错,也陆续隔几天,就能发现重启的记录。但是个人还是希望能够分析出CLOSE_WAIT状态的链接有增无减的具体原因,从而能够根治这个问题。