1. 程式人生 > >SecureRandom生成隨機數超慢 導致tomcat啟動時間過長的解決辦法

SecureRandom生成隨機數超慢 導致tomcat啟動時間過長的解決辦法

tails spa centos 7 屬性 gpo org 解決辦法 hang iss

用騰訊雲的CentOS 7.2 CVM 服務器跑Tomcat時發現,Tomcat啟動的特別慢,通過查看日誌,發現時間主要花在實例化SecureRandom對象上了。

技術分享圖片

由該日誌可以看出,實例化該對象使用了460秒,導致整個應用啟動了480秒之久。

根本原因是SecureRandom 這個jre的工具類的問題.
具體內容:JDK-6521844 : SecureRandom hangs on Linux Systems

那為什麽SecureRandom generateSeed這麽慢,甚至掛在Linux操作系統呢?

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

註意這條日誌:
org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [460,653] milliseconds.

Tomcat 使用SHA1PRNG算法,該算法是基於SHA-1算法實現且保密性較強的偽隨機數生成器。

在SHA1PRNG中,有一個種子產生器,它根據配置執行各種操作。

1)如果Java.security.egd屬性或securerandom.source屬性指定的是”file:/dev/random”或”file:/dev/urandom”,那麽JVM會使用本地種子產生器NativeSeedGenerator,它會調用super()方法,即調用SeedGenerator.URLSeedGenerator(/dev/random)方法進行初始化。

2)如果java.security.egd屬性或securerandom.source屬性指定的是其它已存在的URL,那麽會調用SeedGenerator.URLSeedGenerator(url)方法進行初始化。

這就是為什麽我們設置值為”file:///dev/urandom”或者值為”file:/./dev/random”都會起作用的原因。

在這個實現中,產生器會評估熵池(entropy pool)中的噪聲數量。隨機數是從熵池中進行創建的。當讀操作時,/dev/random設備會只返回熵池中噪聲的隨機字節。/dev/random非常適合那些需要非常高質量隨機性的場景,比如一次性的支付或生成密鑰的場景。

當熵池為空時,來自/dev/random的讀操作將被阻塞,直到熵池收集到足夠的環境噪聲數據。這麽做的目的是成為一個密碼安全的偽隨機數發生器,熵池要有盡可能大的輸出。對於生成高質量的加密密鑰或者是需要長期保護的場景,一定要這麽做。

那麽什麽是環境噪聲?

隨機數產生器會手機來自設備驅動器和其它源的環境噪聲數據,並放入熵池中。產生器會評估熵池中的噪聲數據的數量。當熵池為空時,這個噪聲數據的收集是比較花時間的。這就意味著,Tomcat在生產環境中使用熵池時,會被阻塞較長的時間。

有2種解決方案:

  1. 可以通過配置JRE使用非阻塞的Entropy Source:
    在catalina.sh中加入這麽一行:-Djava.security.egd=file:/dev/./urandom 即可。
    加入後再啟動Tomcat,整個啟動耗時下降到Server startup in 20130 ms。
    這種方案是在修改隨機數獲取方式,那這裏urandom是啥呢?

    /dev/random的一個副本是/dev/urandom(“unblocked”,非阻塞的隨機數發生器[4]),它會重復使用熵池中的數據以產生偽隨機數據。這表示對/dev/urandom的讀取操作不會產生阻塞,但其輸出的熵可能小於/dev/random的。它可以作為生成較低強度密碼的偽隨機數生成器,不建議用於生成高強度長期密碼。 - - - wikipedia

  2. 在JVM環境中解決
    打開$JAVA_PATH/jre/lib/security/java.security這個文件,找到下面的內容:

    securerandom.source=file:/dev/random
    • 1
    • 1

    替換成

    securerandom.source=file:/dev/./urandom
    • 1
    • 1

參考:
1. Tomcat 8熵池阻塞變慢詳解
2. SecureRandom第一次生成隨機數非常慢

來自:http://blog.csdn.net/a9529lty/article/details/76976105

SecureRandom生成隨機數超慢 導致tomcat啟動時間過長的解決辦法