JVM线程阻塞排查

327 阅读1分钟

阻塞线程堆栈查看

  1. 查看java进程id ps -ef|grep java
  2. 找到cpu使用率较高的线程id,将线程id转换为16进制 ps p 16480 -L -o pcpu,pid,tid,time,tname,cmd
  3. 查看进程堆栈信息,输出到16480.pid jstack -l 16480 > 16480.pid jstack -l 16480 | grep 54ee(16进制)

此次线程现象及原因

大批量数据多线程进行跑批,跑到一多半时,有1-2个线程阻塞,查看堆栈信息显示数据库连接socket读取阻塞。当阻塞大概2个小时后抛出异常,异常见下图,前台服务查询均正常。异常表示是mysql连接失效。 线程阻塞时堆栈信息显示为com.mysql.jdbc.util.ReadAheadInputStream(网络搜索此关键字可以查出类似问题) 初步原因是socket缓存已满。也有可能是服务器防火墙对tcp长连接超时设置,duird数据库连接池连接都为长连接,因防火墙中断导致连接失效。duird连接池有个缺陷是每次拿连接前会校验连接有效性,不会单独起一个线程去检验每个连接是否断开,c3p0连接池有这个逻辑。 解决方案: socket不去预读网络缓冲区,mysql连接增加参数&useUnbufferedInput=true&useReadAheadInput=false 截图.png截图1.png截图2.png截图3.png截图5.png