天天看點

Linux中tomcat啟動很慢,SessionIdGeneratorBase.createSecureRandom耗時5分鐘

通常情況下,tomcat啟動隻要2~3秒鐘,突然有一天,tomcat啟動非常慢,要花5~6分鐘,查了很久,終于在這篇文章找到了解決方案,部落客牛人啊。

原文參見:http://blog.csdn.NET/chszs/article/details/49494701

Tomcat 8啟動很慢,且日志上無任何錯誤,在日志中檢視到如下資訊:

[2017-03-17 14:16:32 198 INFO ] [localhost-startStop-1] - Root WebApplicationContext: initialization completed in 8437 ms (org.springframework.web.context.ContextLoader)
[2017-03-17 14:16:33 364 DEBUG-276] [scheduler_QuartzSchedulerThread] - batch acquisition of 0 triggers (org.quartz.core.QuartzSchedulerThread)
           
[2017-03-17 14:16:33 364 INFO]            
Mar 17, 2017 2:16:51 PM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [342,572] milliseconds.      

原因

Tomcat 7/8都使用org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom類産生安全随機類SecureRandom的執行個體作為會話ID,這裡花去了342秒,也即接近6分鐘。

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在生産環境中使用熵池時,會被阻塞較長的時間

解決

有兩種解決辦法:

1)在Tomcat環境中解決

可以通過配置JRE使用非阻塞的Entropy Source。

在catalina.sh中加入這麼一行:-Djava.security.egd=file:/dev/./urandom 即可。

加入後再啟動Tomcat,整個啟動耗時下降到Server startup in 2912 ms。

2)在JVM環境中解決

打開$JAVA_PATH/jre/lib/security/java.security這個檔案,找到下面的内容:

securerandom.source=file:/dev/urandom
           

替換成

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


           

繼續閱讀