最近在重启生产环境项目后偶尔会出现这个情况:浏览器访问页面,无报错一直处于加载状态,服务器上tomcat日志没有访问记录输出,也没有异常日志输出,再次重启tomcat后才正常运行。
后续经过网上一番查找才得知这是tomcat假死的情况,由于当时情况紧急没有时间排查原因,只忙着重启解决(小型项目,没有做集群),这里就记录一下排查思路,防止下次遇到后再这样暴力解决。
1.项目虽然没有做集群,但是有nginx做反向代理,所以第一步应该是查看nginx上的access.log日志。倘若有访问记录日志打印,则表示前端到nginx无问题。
2.接着排查nginx到tomcat的情况。
查看tomcat的访问日志localhost_acess.log有没有本次请求记录,没有记录先怀疑是否网络有问题。从该台nginx ping 了一下tomcat server ,正常,没有发现问题。既然网络貌似没有问题,开始怀疑是tomcat本身的问题,在tomcat本机直接curl 调用该条请求,发现仍然没有响应。到此基本可以断定网络没有问题,tomcat 本身出现了假死的情况。
基于tomcat 假死的情况,开始分析有可能的原因。造成tomcat假死有可能的情况大概有以下几种:
1.内存溢出
分析当时的gc.log 是否有内存溢出的情况,或者直接grep OutOfMemoryException catalina.sh
查看是否有内存溢出异常。
2.jvm GC 时间过长,导致应用暂停
查看gc.log回收时间,以下为例子:
7581088.402: [Full GC (System) 7581088.402: [CMS: 661091K->669762K(7340032K), 1.7206330 secs] 848607K->669762K(8238848K), [CMS Perm : 34999K->34976K(58372K)], 1.7209480 secs] [Times: user=1.72 sys=0.00, real=1.72 secs]
最近的一次full gc 显示,也不应该会暂停几分钟的情况,这种假死可能可以排除。
3.load 太高,已经超出服务的极限
当时top一下linux
top
load average: 0.02, 0.02, 0.00 Tasks: 272 total, 1 running, 271 sleeping, 0 stopped, 0 zombie Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 99.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 32950500k total, 23173908k used, 9776592k free, 1381456k buffers Swap: 33551744k total, 236k used, 33551508k free, 12320412k cached
load 并不是高,这种假死可能可以排除。
4.应用程序出现死锁,需要使用jstack进行线程分析
5.大量tcp 连接 CLOSE_WAIT
使用命令netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
6.tomcat长连接数超过最大连接数
tomcat默认最大连接数(线程数)200个,默认每一个连接的生命周期2小时(7200秒),tomcat使用http 1.1协议,而http1.1默认是长连接。tomcat接受处理完请求后,socket没有主动关闭,因此如果在2小时内,请求数超过200个,服务器就会出现上述假死现象。解决办法:
1.修改tomcat server.xml配置文件,增大最大连接数
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" acceptCount="500" maxThreads="400" />
2.修改linux的TCP超时时间(socket生命周期)限制
vi /etc/sysctl.conf
# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 30
# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1800
# 探测次数
net.ipv4.tcp_keepalive_probes=2
# 探测间隔秒数
net.ipv4.tcp_keepalive_intvl=2
编辑完 /etc/sysctl.conf,要重启network 才会生效
[root@temp /]# /etc/rc.d/init.d/network restart
网友评论