SecureRandom使用不當引起的線程阻塞


問題起因

一個對外提供的接口,中間需要調用第三方接口,涉及到三方機密問題,其中使用到了安全隨機數
之前的寫法如下

public static String randomCode() {
    Random r = new Random();
    StringBuilder str = new StringBuilder();
    for (int i=0;i<6;i++){
        str.append((r.nextInt(10)));
    }
    return str.toString();
}

被solar掃面到不符合規范於是就改成下面的:

public class CodeUtil {

    private CodeUtil() {}

    // SecureRandom is preferred to Random
    private static Random rand;

    static {
        try {
            rand = SecureRandom.getInstanceStrong();
        } catch (NoSuchAlgorithmException e) {
            log.error("NoSuchAlgorithmException: {}", e);
        }
    }

    public static String randomCode() {
        StringBuilder str = new StringBuilder();
        for (int i=0;i<6;i++){
            str.append((rand.nextInt(10)));
        }
        return str.toString();
    }
}

bug現象

之前所有調用對外暴漏的服務的時候都是正常的,第二天莫名其妙的報錯

 

 

 

 

 

 根據這個報錯很自然就是想到服務調用超時,於是各種設置feign調用超時時間,但是都沒有起到效果,本地測試服務調用時間,發現時間開銷也並不是很高,總是感覺客戶端鏈接一到服務端就斷開了,於是估計因該是服務端的問題,但是本地調用也沒有問題,甚至在服務中sleep了30s,依然沒有顯示超時,排查了一個下午,也沒有搞明白到底是什么錯誤

曙光
當時也不知道是什么力量讓我在服務器上打出了一個top命令,發現了一個叫java的進程,pid為1,於是就jstack了一下,驚喜的返現下面這些懂

 

 

 

 仔細觀察了一下發現所有的http線程都阻塞在了同一把鎖上面,這個時候問題基本已經定位到了
於是還原了一下源代碼,問題成功解決。

SecureRandom.getInstanceStrong(); 是jdk1.8里新增的加強版隨機數實現

如果你的服務器在Linux操作系統上,這里的罪魁禍首是SecureRandom generateSeed()。它使用/dev/random生成種子。但是/dev/random是一個阻塞數字生成器,如果它沒有足夠的隨機數據提供,它就一直等,這迫使JVM等待。鍵盤和鼠標輸入以及磁盤活動可以產生所需的隨機性或熵。但在一個服務器缺乏這樣的活動,可能會出現問題

有2種解決方案:

1. 在Tomcat環境中解決:

可以通過配置 JRE 使用非阻塞的 Entropy Source:
在 catalina.sh 中加入這么一行:-Djava.security.egd=file:/dev/./urandom 即可。
 

2. 在 JVM 環境中解決(本人使用此方法):

打開jdk安裝路徑 $JAVA_PATH/jre/lib/security/java.security 這個文件,找到下面的內容:
securerandom.source=file:/dev/random
替換成:
securerandom.source=file:/dev/./urandom
 

問題完美解決

這里值為何要在 dev 和 random 之間加一個點呢?是因為一個 JDK 的 bug,有人反饋即使對 securerandom.source 設置為
/dev/urandom 它也仍然使用的 /dev/random,有人提供了變通的解決方法,其中一個變通的做法是對 securerandom.source
設置為 /dev/./urandom 才行。也有人評論說這個不是 bug,是有意為之。


————————————————
版權聲明:本文為CSDN博主「你們都是壞孩子00」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/wmq930626/java/article/details/105951216

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM