启动巨慢问题分析 根据启动日志,竟然花了 5 分多钟,然后仔细观察日志,主要是卡在初始化 Session。开始我以为云服务器的问题,然后我在本地虚拟机上同样操作,问题重现,并且更换了 Tomcat7,问题仍然出现,所以。通过搜索和分析,Tomcat 的 SessionID 是通过 SHA1PRNG 算法计算得到的,SHA1 算法需要一个密钥,这个密钥在 Tomcat 启动的时候随机生成一个,生成是使用了 Linux 随机函数生成器/dev/random。读取它相当于生成随机数字。搜索/dev/random,大概知道是什么鬼了:/dev/random会根据 噪音 产生随机数,如果噪音不够它就会阻塞。Linux 是通过 I/O,键盘终端、内存使用量、CPU 利用率等方式来收集噪音的,如果噪音不够生成随机数的时候就会被阻塞。
解决问题 解决上述问题有两个方案,一个使用伪随机函数生成器,另外一个加大/dev/random的熵池,下面分别介绍这两种方案。
A.使用伪随机函数生成器/dev/unrandom /dev/urandom并不是真正的随机行为(其实一般不容易重复),主要有两个地方可以修改。
- 通过修改 Tomcat 启动文件,在catalina.sh中加入这么一行
JAVA_OPTS="-Djava.security.egd=file:/dev/urandom"
- 通过修改 JRE 中的 java.security 文件 securerandom.source=file:/dev/urandom
B.增大/dev/random的熵池(推荐) 问题的原因是由于熵池不够大,所以增大它是最彻底的方法。我们可以通过软件的方法实现,下面是软件的安装和配置流程。
- 安装熵服务
yum install rng-tools - 启动熵服务
systemctl start rngd - 如果你的 CPU 不支持 DRNG 特性或者像我一样使用虚拟机,可以使用/dev/unrandom来模拟。
cp /usr/lib/systemd/system/rngd.service /etc/systemd/system vim /etc/systemd/system/rngd.service #以下是编辑内容 ExecStart=/sbin/rngd -f -r /dev/urandom - 重新载入服务
systemctl daemon-reload systemctl restart rngd
经过上面的修改,我们再观察 /proc/sys/kernel/random/entropy_avail 基本上在 3000 左右。这个时候重新启动 Tomcat,发现启动时间正常。