孤独酒馆|6000+字,30+张图。JAVA线上故障排查全套路总结( 七 )


孤独酒馆|6000+字,30+张图。JAVA线上故障排查全套路总结接下来我们通过wireshark打开抓到的包 , 可能就能看到如下图所示 , 红色的就表示RST包了 。
孤独酒馆|6000+字,30+张图。JAVA线上故障排查全套路总结TIME_WAIT和CLOSE_WAITTIME_WAIT和CLOSE_WAIT是啥意思相信大家都知道 。 在线上时 , 我们可以直接用命令netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'来查看time-wait和close_wait的数量
用ss命令会更快ss -ant | awk '{++S[$1]} END {for(a in S) print a, S[a]}'
孤独酒馆|6000+字,30+张图。JAVA线上故障排查全套路总结img
TIME_WAITtime_wait的存在一是为了丢失的数据包被后面连接复用 , 二是为了在2MSL的时间范围内正常关闭连接 。 它的存在其实会大大减少RST包的出现 。
过多的time_wait在短连接频繁的场景比较容易出现 。 这种情况可以在服务端做一些内核参数调优:
#表示开启重用 。 允许将TIME-WAIT sockets重新用于新的TCP连接 , 默认为0 , 表示关闭net.ipv4.tcp_tw_reuse = 1#表示开启TCP连接中TIME-WAIT sockets的快速回收 , 默认为0 , 表示关闭net.ipv4.tcp_tw_recycle = 1当然我们不要忘记在NAT环境下因为时间戳错乱导致数据包被拒绝的坑了 , 另外的办法就是改小tcp_max_tw_buckets , 超过这个数的time_wait都会被干掉 , 不过这也会导致报time wait bucket table overflow的错 。
CLOSE_WAITclose_wait往往都是因为应用程序写的有问题 , 没有在ACK后再次发起FIN报文 。 close_wait出现的概率甚至比time_wait要更高 , 后果也更严重 。 往往是由于某个地方阻塞住了 , 没有正常关闭连接 , 从而渐渐地消耗完所有的线程 。
想要定位这类问题 , 最好是通过jstack来分析线程堆栈来排查问题 , 具体可参考上述章节 。 这里仅举一个例子 。
开发同学说应用上线后CLOSE_WAIT就一直增多 , 直到挂掉为止 , jstack后找到比较可疑的堆栈是大部分线程都卡在了countdownlatch.await方法 , 找开发同学了解后得知使用了多线程但是确没有catch异常 , 修改后发现异常仅仅是最简单的升级sdk后常出现的class not found 。


推荐阅读