p6spy打印sql日誌線程不安全導致的生產問題

  首先說明下我這個標題可能起的不到位,其實我本次要介紹的是一次生產定位問題的思路及過程。

1.生產現象

   國慶前期發佈了一個很小版本,大家都以爲沒什麼問題,可是發佈後生產出現了問題並且持續了兩個小時以上,現象如下:
ERROR|org.hibernate.engine.jdbc.spi.SqlExceptionHelper|[SimpleAsyncTaskExecutor-52] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:150; busy:150; idle:0; lastwait:60000].
  最直接報錯就是生產應用程序獲取數據庫連接無法正常獲取,當時未進行定位問題的情況下只打印了線程棧快照,堆快照信息未保存,然後擴大數據庫連接,最後重啓,重啓後無問題(當晚未留,第天定位)。

2.線程dump文件分析

這裏涉及到信息安全問題,公司內網無法發送資料,所以本地再現了下,線程棧信息大致如下:
在這裏插入圖片描述
  我們在線程棧統計了正在運行的線程正好是數據庫連接池的最大數目,這裏我們就開始懷疑HashMap高併發非線程安全導致,佔用數據庫連接無法釋放。由於沒有堆信息進行佐證,我們無法石錘
但是這裏很明顯是p6spy打印sql日誌引起的問題,我們可以到它的官網進行求證https://github.com/p6spy/p6spy/pull/318/commits/bba79de399f862b416db9d476e43f3af33ef90f7
在這裏插入圖片描述
這裏很明顯進行了線程安全的改造處理。接下來我們需要做的就是升級p6spy版本號2.3.0以上
至此我們的問題基本可以說定位到了問題,但是我們還需要學會思考,大家知道HashMap高併發容易引起死循環,或者數據丟失,那麼我們遇到問題時如何證明線程無法結束是因爲HashMap導致的死循環呢?

3.問題復現及驗證

1.復現HashMap死循環
這裏我參考了倉頡圖解系列文章的復現demo
代碼如下:

package com.spring.test.deadmap;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class HashMapThread extends Thread {
    private static AtomicInteger ai = new AtomicInteger(0);
    private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(1);

    public void run() {
        while (ai.get() < 100000) {
            map.put(ai.get(), ai.get());
            ai.incrementAndGet();
        }
    }
}
package com.spring.test.deadmap;

public class Test {
    public static void main(String[] args) {
        HashMapThread hmt0 = new HashMapThread();
        HashMapThread hmt1 = new HashMapThread();
        HashMapThread hmt2 = new HashMapThread();
        HashMapThread hmt3 = new HashMapThread();
        HashMapThread hmt4 = new HashMapThread();
        hmt0.start();
        hmt1.start();
        hmt2.start();
        hmt3.start();
        hmt4.start();
    }
}

使用低版本jdk較容易復現死循環,多試幾次。
2.證明線程無法結束是因爲HashMap存在環
    我們需要藉助堆快照形成堆內實例dump文件,藉助MAT進行分析當前HashMap.Entry[]數組中的Entry鏈表是否存在循環引用
在這裏插入圖片描述
顯然我們當前未結束線程的持有HashMap中存在環引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章