Ubuntu环境Tomcat 9.0.46中Jersey-Spring API的ContextLoader重复初始化3次问题求助
分析与解决:Ubuntu Tomcat下Jersey-Spring应用重复初始化Bean的问题
Hey there, let's dig into why your identical WAR behaves differently on Ubuntu vs Windows Tomcat, and how to fix the repeated ContextLoader triggers and singleton bean instantiations.
核心现象回顾
- 相同的Jersey-Spring WAR包,在Windows Tomcat 9.0.46运行正常,单例Bean仅初始化一次
- 部署到Ubuntu Tomcat 9.0.46(绑定80/443端口,使用Godaddy证书)后:
- 第一次正常完成部署,Bean初始化完毕
- 等待约10分钟(对应日志中
SecureRandom生成耗时)后,ContextLoader被触发两次,Bean再次初始化两次 - 日志中存在关键警告:
Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [584,064] milliseconds
可能的原因分析
1. Ubuntu系统熵池不足导致SecureRandom阻塞(最关键)
Ubuntu默认的SecureRandom实现依赖系统熵池(用于生成安全随机数),当服务器熵值不足时,Tomcat会阻塞等待熵池填充,这直接导致了10分钟的启动延迟。在这段延迟期间,Tomcat的部署流程可能被判定为未完成,进而触发重复部署逻辑。
2. Tomcat自动部署机制重复触发
Ubuntu下Tomcat的文件系统监听器对webapps目录的变化更敏感:
- 如果
autoDeploy默认开启,WAR包解压过程中的临时文件、权限变更,甚至Tomcat运行用户的文件访问差异,都可能触发Tomcat重新检测并部署应用。 - 延迟期间的异常状态,也可能让Tomcat认为之前的部署失败,从而重复执行部署流程。
3. 端口绑定与生命周期事件异常
绑定80/443端口时,因SecureRandom阻塞导致的启动延迟,可能干扰了Tomcat容器的生命周期事件顺序,触发了额外的上下文初始化流程。
分步解决办法
第一步:解决SecureRandom阻塞问题(优先处理)
这是导致延迟和后续连锁问题的根源,修改Tomcat的JVM参数,使用非阻塞的随机数源:
- 在Tomcat的
bin目录下创建/编辑setenv.sh文件(Ubuntu下默认不存在),添加:CATALINA_OPTS="-Djava.security.egd=file:/dev/./urandom"注:
/dev/./urandom是/dev/urandom的别名,避免JVM对路径的特殊解析,它会非阻塞地生成随机数,彻底解决熵池不足的问题。 - 重启Tomcat,验证日志中
SecureRandom的警告是否消失,启动时间是否大幅缩短。
第二步:关闭Tomcat自动部署机制
避免文件系统变化触发重复部署:
- 打开
conf/server.xml,找到对应的<Host>节点,修改配置:<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="false" deployOnStartup="true">autoDeploy="false":关闭启动后的目录监控,禁止自动重新部署deployOnStartup="true":仅在Tomcat启动时一次性部署应用
- (可选)如果想彻底隔离自动部署,可以将WAR包移到
webapps外的目录,通过自定义上下文配置加载:
在conf/Catalina/localhost/skd-service.xml中添加:<Context docBase="/path/to/your/skd-service.war" reloadable="false"/>
第三步:检查文件权限与目录一致性
确保Ubuntu下Tomcat运行用户(通常是tomcat用户)对以下路径有完整权限:
- WAR包所在目录
webapps目录- Tomcat的
temp和work目录
权限不足可能导致解压或文件写入失败,触发Tomcat的重复部署重试逻辑。
第四步:排除Spring/Jersey配置重复
虽然Windows下正常,但可以快速排除配置问题:
- 检查
web.xml中是否重复注册了ContextLoaderListener - 确认Spring的
@Configuration类没有重复的@ComponentScan路径 - 检查Jersey与Spring的集成配置(如
SpringConfig)是否存在重复加载逻辑
验证效果
完成上述配置后,重启Tomcat:
- 启动时间应大幅缩短(不再有10分钟延迟)
- 日志中应仅出现一次
Root WebApplicationContext initialized的信息 - 单例Bean仅初始化一次,不再出现重复实例化的情况
内容的提问来源于stack exchange,提问作者Eng. Samir Fares
相关产品推荐
相关产品推荐

