[轉帖]JFR 定位因為 SSL 導致 CPU Load 飈高的問題

济南小老虎發表於2024-05-16
https://juejin.cn/post/6877132677854527495

專欄:
Java JFR全解

問題場景

在某一時刻,某個微服務的某個例項 CPU 負載突然飈高:

image

同時建立了很多資料庫連結: image

其他例項沒有這個現象。

問題定位

由於建立了很多資料庫連結,猜想可能是資料庫比較慢,檢視資料庫這段時間的 SQL 統計,發現資料庫並不慢:

image

其中這個微服務這段時間的熱點 SQL,執行並不慢。那麼問題出在了哪裡呢?可能是由於 GC,可能是由於 safepoint,還有可能是獲取鎖時間過長(參考:Java 監控 JFR全解),我們 dump 一下 JFR 並檢視其中的 safepoint,GC 以及 Monitor Blocked 相關事件。

首先檢視GC,發現都是 Young GC, GC 暫停時間也可以接受。

image

然後是 safepoint,雖然有采集到 safepoint,但是暫停時間也沒有很長。

image

最後檢視 Java Monitor Block,發現有很多很長時間的鎖等待:

image

堆疊顯示,阻塞在:void sun.security.provider.SecureRandom.engineNextBytes(byte[])上面,這就是一個經典的問題,Java Random,參考程式碼:NativePRNG

arduino
複製程式碼
// name of the *System* property, takes precedence over PROP_RNDSOURCE
private static final String PROP_EGD = "java.security.egd";
// name of the *Security* property
private static final String PROP_RNDSOURCE = "securerandom.source";

private static final boolean useLegacyDSA =
    Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty
        ("jdk.security.legacyDSAKeyPairGenerator"));

static final String URL_DEV_RANDOM = "file:/dev/random";
static final String URL_DEV_URANDOM = "file:/dev/urandom";

涉及到兩種隨機數 seed 生成方式,一種是"file:/dev/random",另一種是"file:/dev/urandom",透過設定系統屬性java.security.egd指定,預設是"file:/dev/random"

兩種 Random 原理與解決

在 Linux 4.8 之前:

image

在 Linux 4.8 之後:

image

在熵池不夠用的時候,預設的"file:/dev/random"會阻塞,"file:/dev/urandom"不會,繼續用。對於我們來說,"file:/dev/urandom"夠用,所以透過-Djava.security.egd=file:/dev/./urandom設定系統屬性,使用 urandom 來減少阻塞。

相關文章