【解决】Linux Tomcat启动慢--Creation of SecureRandom instance for session ID generation using [SHA1PRNG] to...

本文探讨了Tomcat启动过程中因SecureRandom实例化导致的延迟问题。通过分析Linux随机数生成原理,提出了三种解决方案:安装并配置rng-tools服务、修改JVM参数以及调整Tomcat启动参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

今天部署项目到tomcat,执行./startup.sh命令之后,访问项目迟迟加载不出来,查看日志又没报错(其实是我粗心了,当时tomcat日志还没打印完),一开始怀疑是阿里云主机出现问题,访问ip:80发现nginx运行正常。在我百思不得其解时,项目访问正常了,查看启动日志,发现如下:

15-Mar-2018 16:41:02.302 WARNING [main] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [236,325] milliseconds.

可以看出实例化SecureRandom花了接近4分钟!

二、调查

网上搜索到的信息如下:

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

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.

三、解决

方案有3个

方案1:通过rng-tools自动补充熵池(推荐)

yum install rng-tools      #安装rngd熵服务

systemctl start rngd       #启动服务
cp /usr/lib/systemd/system/rngd.service /etc/systemd/system cd /etc/systemd/system/

vim rngd.service
ExecStart=/sbin/rngd -f 改为 ExecStart=/sbin/rngd -f -r /dev/urandom
systemctl daemon-reload   #重新载入服务 

systemctl restart rngd #重启服务

重启tomcat,查看日志,启动时间1271 ms

15-Mar-2018 17:28:24.092 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1271 ms

方案2:修改jvm参数

通过修改JRE中的java.security文件securerandom.source=file:/dev/urandom

重启tomcat,查看日志,启动时间1271 ms

15-Mar-2018 17:22:27.363 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 84777 ms

可见启动速度比原来快了一半多,但还是不理想

方案3:修改tomcat参数

通过修改Tomcat启动文件-Djava.security.egd=file:/dev/urandom(没尝试过)

四、小插曲

总算解决,但是这个问题之前没有的啊,为什么呢?

回想一下,这是我修改代码之后才出现的。所以我将一个继承自HttpServlet的类中

private static final long serialVersionUID = 1L;

改为

private static final long serialVersionUID = -9135576688701595777L;

重启tomcat,查看日志

15-Mar-2018 16:07:02.781 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1267 ms

 tomcat恢复了往日的神速!可是serialVersionUID这个对象的序列化值为什么会影响导致这个问题呢,在一篇《弄懂serialVersionUID》文献中说到

使用默认序列号jvm会使用自身的算法(算法介绍),其中涉及到了SHA1,就我的理解用到了熵值算法,熵池不够所以实例化慢,实证的话要再去看jvm规范,能力有限,以后再爬坑。

以上!

 

转载于:https://www.cnblogs.com/zhangyuejia/p/8575080.html

信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib 6月 07, 2025 4:55:21 下午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-nio-0.0.0.0-8080"] 6月 07, 2025 4:55:21 下午 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector 信息: Using a shared selector for servlet write/read 6月 07, 2025 4:55:21 下午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["ajp-nio-8009"] 6月 07, 2025 4:55:21 下午 org.apache.coyote.AbstractProtocol init 严重: Failed to initialize end point associated with ProtocolHandler ["ajp-nio-8009"] java.lang.IllegalArgumentException: timeout < 0 at java.base/sun.nio.ch.ServerSocketAdaptor.setSoTimeout(ServerSocketAdaptor.java:162) at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:352) at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:823) at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:476) at org.apache.catalina.connector.Connector.initInternal(Connector.java:960) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) at org.apache.catalina.core.StandardService.initInternal(StandardService.java:568) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:871) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) at org.apache.catalina.startup.Catalina.load(Catalina.java:592) at org.apache.catalina.startup.Catalina.load(Catalina.java:615) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:308) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:482) 6月 07, 2025 4:55:21 下午 org.apache.catalina.core.StandardService initInternal 严重: Failed to initialize connector [Connector[AJP/1.3-8009]] org.apache.catalina.LifecycleException: Failed to initialize component [Connector[AJP/1.3-8009]] at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107) at org.apache.catalina.core.StandardService.initInternal(StandardService.java:568) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:871) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) at org.apache.catalina.startup.Catalina.load(Catalina.java:592) at org.apache.catalina.startup.Catalina.load(Catalina.java:615) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:308) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:482) Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed at org.apache.catalina.connector.Connector.initInternal(Connector.java:962) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102) ... 12 more Caused by: java.lang.IllegalArgumentException: timeout < 0 at java.base/sun.nio.ch.ServerSocketAdaptor.setSoTimeout(ServerSocketAdaptor.java:162) at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:352) at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:823) at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:476) at org.apache.catalina.connector.Connector.initInternal(Connector.java:960) ... 13 more 6月 07, 2025 4:55:21 下午 org.apache.catalina.startup.Catalina load 信息: Initialization processed in 8287 ms 6月 07, 2025 4:55:22 下午 org.apache.catalina.core.StandardService startInternal 信息: Starting service Catalina 6月 07, 2025 4:55:22 下午 org.apache.catalina.core.StandardEngine startInternal 信息: Starting Servlet Engine: Apache Tomcat/8.0.53 6月 07, 2025 4:55:29 下午 org.apache.jasper.servlet.TldScanner scanJars 信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 6月 07, 2025 4:55:30 下午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom 警告: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [319] milliseconds. 6月 07, 2025 4:55:34 下午 org.apache.jasper.servlet.TldScanner scanJars 信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 6月 07, 2025 4:55:34 下午 org.apache.coyote.AbstractProtocol start 信息: Starting ProtocolHandler ["http-nio-0.0.0.0-8080"] 6月 07, 2025 4:55:35 下午 org.apache.catalina.startup.Catalina start
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值