一次服务假死

服务假死 通过ip+port无法访问。通过 jmap -heap pid 和 jstat -gcutil pid 发现内存占用率并不高 gc次数也比较正常。 通过在网上搜索, 用 lsof命令发现该端口有大量CLOSE_WAIT状态的连接。用 jstack -l pid 打印出线程的堆栈信息。直接打印出的 信息比较难以分析。暂时找到 https://gceasy.io/same-state-threads.jsp 这个网站,分析发现线程数很多达到了800+,大部分的 线程都在 WAITING,很多都是卡在 HealthIndicatorBeansComposite$ReactiveHealthIndicators 这里。reactive模式的代码真是 太难看懂了,只能先猜测是 RedisHealthIndicator卡住了,访问 /actuator/health确实卡死。猜测是 Actuator的健康检查出错。 然后屏蔽调 RedisHealthIndicator的逻辑,/actuator/health正常返回。 总结一下就是 服务卡死先看 内存和GC的情况,jmap -heap 查看是否属于内存泄露的问题。还需要检查服务端口的连接是否正常,会不会有大量的 CLOSE_WAIT和TIME_WAIT状态的连接,CLOSE_WAIT是被动关闭方的状态,TIME_WAIT是主动关闭方的状态。这种状态比较多一般是 大部分线程卡死了, jstack -l 看一下,很有可能是线程都 wait了。

top -Hp pid 可以看该进程下的所有线程,可以找到使用率高到不正常的几个线程,(shift + P 按cpu排序,shift + M 按内存排序)不过线程ID都是十进制的,需要 转成十六进制。直接 printf ’%x\n‘ number 可以转成16进制 然后 jstack -l | grep 16进制 -A 30 定位线程信息

注 grep -A 是看后n行 -B 是看前n行 -C 看前后n行

Written on July 31, 2019