阻塞线程堆栈查看
- 查看java进程id ps -ef|grep java
- 找到cpu使用率较高的线程id,将线程id转换为16进制 ps p 16480 -L -o pcpu,pid,tid,time,tname,cmd
- 查看进程堆栈信息,输出到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