场景:项目使用的是springboot开发。在本机启动,大概完成的时间是20s左右,但是部署到Centos6.5服务器上启动要300s以上。
原因:
SHA1PRNG算法是基于SHA-1算法实现且保密性较强的伪随机数生成器。
在SHA1PRNG中,有一个种子产生器,它根据配置执行各种操作。
Linux中的随机数可以从两个特殊的文件中产生,一个是/dev/urandom.另外一个是/dev/random。他们产生随机数的原理是利用当前系统的熵池来计算出固定一定数量的随机比特,然后将这些比特作为字节流返回。熵池就是当前系统的环境噪音,熵指的是一个系统的混乱程度,系统噪音可以通过很多参数来评估,如内存的使用,文件的使用量,不同类型的进程数量等等。如果当前环境噪音变化的不是很剧烈或者当前环境噪音很小,比如刚开机的时候,而当前需要大量的随机比特,这时产生的随机数的随机效果就不是很好了。
这就是为什么会有/dev/urandom和/dev/random这两种不同的文件,后者在不能产生新的随机数时会阻塞程序,而前者不会(ublock),当然产生的随机数效果就不太好了,这对加密解密这样的应用来说就不是一种很好的选择。/dev/random会阻塞当前的程序,直到根据熵池产生新的随机字节之后才返回,所以使用/dev/random比使用/dev/urandom产生大量随机数的速度要慢
解决:
tomcat的文档里有个概念叫Entropy Source(熵源),在启动时会调用SecureRandom类来生成随机数。如果用于初始化SecureRandom的熵源是个短熵(熵不够用),那么就会报文章开头说的warning了。
jdk默认配置的熵源是file:/dev/random,通过如下命令查看
cat $JAVA_HOME/jre/lib/security/java.security | grep securerandom
所以程序启动后SecureRandom类会读取/dev/random以获取随机序列,这是一个同步操作。当熵池中没有足够的熵时,读取/dev/random就会造成阻塞,直到收集到了足够的熵,程序才会继续往下进行。此处用了95秒。
解决办法就是改用为非阻塞的熵源/dev/./urandom,可以修改jdk配置文件,也可以在程序启动时候指定。
在启动时增加参数 -Djava.security.egd=file:/dev/./urandom
即启动脚本文为 java -jar -Djava.security.egd=file:/dev/./urandom xxx.jar
参考:
https://blog.csdn.net/qq_25152183/article/details/73228997
https://blog.csdn.net/catcher92/article/details/86611678