前情提要:公司新引入了sonar對代碼監測,由此根據sonar提出的建議修改了生成隨機數的Random類。
修改前:
1 Random random = new Random(); 2 int num = random.nextInt(200); 3 System.out.println("生成隨機數num=" + num);
修改后:
1 int num = 200; 2 3 try { 4 Random random = SecureRandom.getInstanceStrong(); 5 num = random.nextInt(200); 6 } catch (Exception ex) { 7 logger.error("生成隨機數失敗:" + ex.getMessage()); 8 } 9 10 System.out.println("生成隨機數num=" + num);
修改完之后,運行了大概1天還是2天,后面有人反饋調用失敗,實際是超時。
查詢后台發現:調用的接口執行時間都在1分鍾兩分鍾以上,每次都運行超時。打印的也都是num=200,隨機數每次都是200,這才懷疑可能是之前根據sonar建議改過造成的。
但是在windows的測試案例里跑,兩段代碼並沒有什么不一樣,執行效果都挺快。帶着試一試的心態修改了代碼,部署到Linux機器上,問題終於迎刃而解。
后面在網上查詢資料發現:(摘取其中的一段)
1 如果你的服務器在Linux操作系統上,這里的罪魁禍首是SecureRandom generateSeed()。 2 它使用/dev/random生成種子。但是/dev/random是一個阻塞數字生成器,如果它沒有足夠的隨機數據提供,它就一直等,這迫使JVM等待。 3 鍵盤和鼠標輸入以及磁盤活動可以產生所需的隨機性或熵。但在一個服務器缺乏這樣的活動,可能會出現問題。
有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
// 以上引用自:http://www.manongjc.com/detail/18-lpszfgoaxerlvil.html
當然,除了以上2種解決方案外,你還可以不使用SecureRandom。