1. 程式人生 > 實用技巧 >重啟tomcat後,訪問登陸介面響應慢--Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [27,572] milliseconds.

重啟tomcat後,訪問登陸介面響應慢--Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [27,572] milliseconds.

一:背景

在重啟tomcat後,直接訪問登陸介面,服務響應特別的慢,檢視日誌發現:

WARN http-nio-9977-exec-2 SessionIdGeneratorBase - Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [27,572] milliseconds.

可以看出例項化SecureRandom花了27s

二:調查

Tomcat 7/8/9 都使用 org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 類產生安全隨機類 SecureRandom 的例項作為會話 ID。

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

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

Linux 中的隨機數可以從兩個特殊的檔案中產生,一個是 /dev/urandom,另外一個是 /dev/random。他們產生隨機數的原理是利用當前系統的熵池來計算出固定一定數量的隨機位元,然後將這些位元作為位元組流返回。熵池就是當前系統的環境噪音,熵指的是一個系統的混亂程度,系統噪音可以通過很多引數來評估,如記憶體的使用,檔案的使用量,不同型別的程序數量等等。如果當前環境噪音變化的不是很劇烈或者當前環境噪音很小,比如剛開機的時候,而當前需要大量的隨機位元,這時產生的隨機數的隨機效果就不是很好了。

這就是為什麼會有 /dev/urandom 和 /dev/random 這兩種不同的檔案,後者在不能產生新的隨機數時會阻塞程式,而前者不會(ublock),當然產生的隨機數效果就不太好了,這對加密解密這樣的應用來說就不是一種很好的選擇。/dev/random 會阻塞當前的程式,直到根據熵池產生新的隨機位元組之後才返回,所以使用 /dev/random 比使用 /dev/urandom 產生大量隨機數的速度要慢。

SecureRandom generateSeed 使用 /dev/random 生成種子。但是 /dev/random 是一個阻塞數字生成器,如果它沒有足夠的隨機資料提供,它就一直等,這迫使 JVM 等待。鍵盤和滑鼠輸入以及磁碟活動可以產生所需的隨機性或熵。但在一個伺服器缺乏這樣的活動,可能會出現問題。

**********************************************************************************************

說得很清楚,就是隨機數生成問題。上述觀點在jdk中SecureRandom類的註釋得到了印證:

 * Note: Depending on the implementation, the {@code generateSeed} and
 * {@code nextBytes} methods may block as entropy is being gathered,
 * for example, if they need to read from /dev/random on various Unix-like
 * operating systems.

三:解決

方法一:
開啟$JAVA_PATH/jre/lib/security/java.security這個檔案,找到下面的內容: securerandom.source=file:/dev/urandom 替換成 securerandom.source=file:/dev/./urandom

方法二:
在啟動SpringBoot專案的jar包時加上
-Djava.security.egd=file:/dev/./urandom 引數
或者在tomcat的catlina.sh檔案中加上配置 -Djava.security.egd=file:/dev/./urandom