Tomcat启动Creation of SecureRandom instance卡住解决办法
本文描述Tomcat启动因为 Creation of SecureRandom instance for session ID generation using [SHA1PRNG] 卡住的问题,以及解决办法
注:我的独立博客对应链接:Tomcat启动Creation of SecureRandom instance卡住解决办法
背景
起因是线上Tomcat的启动缓慢,看到日志里面有一行:
[2019-05-17 14:06:20] [localhost-startStop-1] INFO o.a.c.util.SessionIdGenerator [T:] Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [213,586] milliseconds.
原因
简单google了一下,是Java的SecureRandom是同步读的操作系统的/dev/random
(具体的这个配置是在JAVA_HOME/jre/lib/security/java.security这个文件里面的securerandom.source=file:/dev/random 这个配置项)
由于entropy pool(熵池)里面的值不够,所以卡住在读/dev/random上了,造成了启动缓慢
解决方法
1. 根据tomcat官方文档给出的方式(https://wiki.apache.org/tomcat/HowTo/FasterStartUp),在jvm启动的时候加入-Djava.security.egd=file:/dev/./urandom即可
2. 或者把JAVA_HOME/jre/lib/security/java.security里面的securerandom.source的值改为file:/dev/./urandom也可以
上述方法二选一即可。
./urandom是什么鬼
但是这里有个很奇怪的地方,为什么写法是file:/dev/./urandom,而不是file:/dev/urandom,我搜索了一下,换成file:/dev/urandom是不会生效的,读的还是file:/dev/random。这是jvm的一个bug,相关的记录
If java.security.egd or securerandom.source point to "file:/dev/random" or "file:/dev/urandom", we will use NativeSeedGenerator, which calls super() which calls SeedGenerator.URLSeedGenerator(/dev/random).
(A nested class within SeedGenerator.) The only things that changed in this bug was that urandom will also trigger use of this code path.
其实最后都call到同一个SeedGenerator.URLSeedGenerator(/dev/random)上面去了
所以才有了这个workaround用file:/dev/./urandom这个格式。
但是这个问题在开发环境并不存在,为什么预发/线上会有?
因为我们的开发环境是redhat,线上是debian , 直接cat /dev/random就能发现开发环境能马上显示好几屏的随机数,而线上环境只有不到20个字符。具体/dev/random是啥见wikipedia:/dev/random.
这里摘取其中的一段
随机数发生器有一个容纳噪声数据的熵池,在读取时,/dev/random设备会返回小于熵池噪声总数的随机字节。
/dev/random可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止。
这样的设计使得/dev/random是真正的随机数发生器,提供了最大可能的随机数据熵,建议在需要生成高强度的密钥时使用。
/dev/random的一个副本是/dev/urandom(“unblocked”,非阻塞的随机数发生器),它会重复使用熵池中的数据以产生伪随机数据。
这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。
它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。
/dev/random也允许写入,任何用户都可以向熵池中加入随机数据。
即使写入非随机数据亦是无害的,因为只有管理员可以调用ioctl以增加熵池大小。
Linux内核中当前熵的值和大小可以通过访问/proc/sys/kernel/random/文件夹中的文件得到
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步