線上發現執行某特定任務在某個特定時間點後再也不work。該任務由線程池中線程執行定時週期性調度,根據日誌查看無任何異常。從代碼研判應該無關定時任務框架,由於對提交的定時任務作了wrap,會將異常都catch住,保證下次仍然可以正常調度。php
經過jstack導出堆棧信息,發現問題線程的堆棧信息以下:html
"OperatorDispatch" #338 prio=5 os_prio=0 tid=0x00007f1140d63000 nid=0x2edc runnable [0x00007f101f8cd000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:101) at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:144) at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:174) - locked <0x00000006c4a6d190> (a com.mysql.jdbc.util.ReadAheadInputStream) at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3008) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3469) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3459) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3900) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490) - locked <0x00000006c501d648> (a com.mysql.jdbc.JDBC4Connection) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858) - locked <0x00000006c501d648> (a com.mysql.jdbc.JDBC4Connection) at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197) 省略
研判出線程hang在socketRead0方法中,仔細排查後發現socketRead0中的timeout爲0,也即沒有超時設定。java
網上對於此問題有很多說法,有的是說讀取大量數據時會出現,須要設置limit。也有人提交了相關的bug,如74379mysql
我卻是以爲深刻理解JDBC的超時設置這篇文章不錯,也傾向於緣由是網絡抖動,但不管如何應用層的應該對socket鏈接設置超時參數。sql
最終在jdbc鏈接串中加上socketTimeout參數設定超時時間。segmentfault