一 、概況
採用springboot的jpa讀取oracle的數據,大概300萬數據,運行一天左右之後,程序卡死,導致數據接入接不完。
二、排查思路
java生產級別的接入程序卡死是正常的,基本重啓就可以解決問題,但是重啓之後還是會卡死,所以要排查原因,找到源頭。
基本的思路就是查看代碼堆棧,是否是線程死鎖、遇到阻塞隊列、或者線程池線程因爲內存不足退出等。
基本使用的工具包括jstack命令查看堆棧,jconsole查看線程狀態及內存狀態,jvisualvm查看內存數據及線程運行情況等
三、採用jstack查看接入代碼卡住的部分
執行jstack pid,具體核心部分如下:
通過上述的堆棧可以看出,代碼卡在socket讀取數據的部分,並且鎖住了一個oracle連接(這個地方是導致執行了kill -15 之後,程序不退出的原因)。
這就奇怪了,代碼明明設置了超時時間的呢,那咋回事???,狂搜百度,無果,這個時候肯定想看下oracle.jdbc.driver.T4CConnection這個對象內部的值等。
四、如何看jvm對象的值
通過jdk提供的工具jvisualvm,可以分析jvm的內存佔用情況及其對象的值等,是不是很強大,哈哈
通過上述oracle連接對象的內存分析,發現有thinNetConnectionTimeOut和thinReadTimeOut兩個參數,第一個設置爲30000ms,第二個爲null,原來是沒設置讀取超時啊。
五、如何設置oracle連接的讀取超時
啓動的時候,在jvm參數裏面添加-Doracle.jdbc.ReadTimeout=1800000即可。
六、kill -15爲什麼殺不死程序
kill -15是安全退出進程機制,沒有kill -9 這麼暴力,此次未推出的原因如下:
jvm接收到推出的命令之後,springboot的jpa連接池會回收掉oracle的連接,但是由於上述第三章內容,代碼卡在讀取數據,連接被上了鎖,所以回收線程一直處於阻塞狀態,導致進程一直推出不了。