现象如下:

1、项目启动日志正常,Spring或者MVC框架也正常加载完成。但是对外无法访问,何解?

2、Tomcat无法正常关闭,因为shutdown port不可用。只能kill。

3、Jstack内容太多,很难查出问题,但基本上可以确认项目所有bean、线程都是正常的。

4、注意到一个细节,Tomcat正常启动和奇怪异常之间,日志最后有一点差别:正常启动后,tomcat最后会打印如下

Aug 10, 2020 1:47:03 PM org.apache.coyote.AbstractProtocol start

INFO: Starting ProtocolHandler ["http-nio-9500"]

异常启动时,没有这两行信息(但是9500端口是有的)。除此之外,其他日志完全相同。

排查思路:

1、框架、组件问题?会不会是框架、或组件(比如Log)某处线程阻塞了?

由于项目代码,包括框架和组件,都是我完全可控的(源码级别的熟悉),所以简单分析了一遍之后,我可以肯定框架和组件没有问题。

2、Tomcat自身问题(某个版本的Tomcat在某个Linux系统上触发了一个bug?)

升级Tomcat到最新版本,问题依旧。

3、既然是环境问题,那很可能与项目无关,将项目换成一个简单servlet项目,问题也应该一模一样。

去掉项目复杂的内容,仅保留简单的servlet,然后排查Jstack,此时jstack内容很少,很容易定位问题。

于是我发现下面一段线程信息,根据我的经验,似曾相识:

"localhost-startStop-1" #13 daemon prio=5 os_prio=0 tid=0x00007f2fbc1db000 nid=0x6243 runnable [0x00007f2ff0f11000]

   java.lang.Thread.State: RUNNABLE

    at java.io.FileInputStream.readBytes(Native Method)

    at java.io.FileInputStream.read(FileInputStream.java:255)

    at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedBytes(SeedGenerator.java:539)

    at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:144)

    at sun.security.provider.SecureRandom$SeederHolder.<clinit>(SecureRandom.java:203)

    at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:221)

    - locked <0x00000000e362dc00> (a sun.security.provider.SecureRandom)

    at java.security.SecureRandom.nextBytes(SecureRandom.java:468)

    at java.security.SecureRandom.next(SecureRandom.java:491)

    at java.util.Random.nextInt(Random.java:329)

    at org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom(SessionIdGeneratorBase.java:269)

    at org.apache.catalina.util.SessionIdGeneratorBase.getRandomBytes(SessionIdGeneratorBase.java:203)

    at org.apache.catalina.util.StandardSessionIdGenerator.generateSessionId(StandardSessionIdGenerator.java:34)

    at org.apache.catalina.util.SessionIdGeneratorBase.generateSessionId(SessionIdGeneratorBase.java:195)

    at org.apache.catalina.util.SessionIdGeneratorBase.startInternal(SessionIdGeneratorBase.java:289)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)

    - locked <0x00000000e362ccf0> (a org.apache.catalina.util.StandardSessionIdGenerator)

    at org.apache.catalina.session.ManagerBase.startInternal(ManagerBase.java:626)

    at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:350)

    - locked <0x00000000edb4ee70> (a org.apache.catalina.session.StandardManager)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)

    - locked <0x00000000edb4ee70> (a org.apache.catalina.session.StandardManager)

    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5184)

    - locked <0x00000000ed08dd60> (a org.apache.catalina.core.StandardContext)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)

    - locked <0x00000000ed08dd60> (a org.apache.catalina.core.StandardContext)

    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)

    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)

    at java.util.concurrent.FutureTask.run(FutureTask.java:266)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

    at java.lang.Thread.run(Thread.java:748)

下面这两句是我熟悉的:

java.io.FileInputStream.readBytes(Native Method)

java.security.SecureRandom.nextBytes

Tomcat确实有个bug,在执行SecureRandom可能非常缓慢(甚至卡住)。

触发这个Bug的前提是,项目中使用了随机数Random类。

于是百度一下,具体原因及解决方案就出来了:

原因:

1、SecureRandom 这个 jre 的工具类的问题。

    Linux 中的随机数可以从两个特殊的文件中产生,一个是 /dev/urandom,另外一个是 /dev/random。他们产生随机数的原理是利用当前系统的熵池来计算出固定一定数量的随机比特,然后将这些比特作为字节流返回。熵池就是当前系统的环境噪音,熵指的是一个系统的混乱程度,系统噪音可以通过很多参数来评估,如内存的使用,文件的使用量,不同类型的进程数量等等。如果当前环境噪音变化的不是很剧烈或者当前环境噪音很小,比如刚开机的时候,而当前需要大量的随机比特,这时产生的随机数的随机效果就不是很好了。

    这就是为什么会有 /dev/urandom 和 /dev/random 这两种不同的文件,后者在不能产生新的随机数时会阻塞程序,而前者不会(ublock),当然产生的随机数效果就不太好了,这对加密解密这样的应用来说就不是一种很好的选择。/dev/random 会阻塞当前的程序,直到根据熵池产生新的随机字节之后才返回,所以使用 /dev/random 比使用 /dev/urandom 产生大量随机数的速度要慢。

    SecureRandom generateSeed  使用 /dev/random 生成种子。但是 /dev/random 是一个阻塞数字生成器,如果它没有足够的随机数据提供,它就一直等,这迫使 JVM 等待。键盘和鼠标输入以及磁盘活动可以产生所需的随机性或熵。但在一个服务器缺乏这样的活动,可能会出现问题。

2、Tomcat 7/8 都使用 org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 类产生安全随机类 SecureRandom 的实例作为会话 ID。

解决方案:

1、启动JVM参数中添加:-Djava.security.egd=file:/dev/./urandom 即可。

2. 修改JVM配置

打开 $JAVA_PATH/jre/lib/security/java.security 这个文件,找到下面的内容:

securerandom.source=file:/dev/random

替换成:

securerandom.source=file:/dev/./urandom

Tomcat启动卡住、无法访问问题解决思路相关推荐

  1. 解决Linux环境下Tomcat启动卡住问题

    解决Linux环境下Tomcat启动卡住问题 参考文章: (1)解决Linux环境下Tomcat启动卡住问题 (2)https://www.cnblogs.com/0xcafedaddy/p/7193 ...

  2. tomcat启动后无法访问到8080页面的原因

    tomcat启动后无法访问到8080页面的原因 原因一:tomcat服务关闭 注意启动 Tomcat 服务器的窗口不要关闭,否则就是意味着关闭了tomcat服务,自然也就看不到页面 原因二:环境变量配 ...

  3. tomcat启动乱码及访问项目中文乱码终极解决方法

    现在我们会发现部署在服务器上的tomcat启动时或者访问项目时都会出现乱码的情况,今天小编就整理了解决这些乱码的解决办法. 1.解决tomcat启动时黑框中出现乱码: (一般tomcat出现乱码都是字 ...

  4. Tomcat 启动卡住

    2019独角兽企业重金招聘Python工程师标准>>> Tomcat启动时,在org.apache.catalina.startup.HostConfig.deployWAR Dep ...

  5. 关于 tomcat启动后无法访问的问题(localhost:8080 (or your port specified))

    [0]README 1)启动 tomcat7, 然后通过 localhost:8080 无法访问,我也是醉了:以下给出了解决方法: [1]解决方法(如何让 Server Locations  和 de ...

  6. Tomcat启动成功能访问主页面但是不能访问应用解决办法

    还是之前做的登录系统,现在要部署到服务器上. 问题:在我本地能访问,在服务器上Tomcat主页面能访问,访问应用报404. 首先将Tomcat拷贝到服务器的某个目录,解压得到文件夹 然后将应用打成wa ...

  7. linux部署tomcat启动后无法访问,linux中启动tomcat后浏览器无法访问的解决方法

    前言 不论是要启动,还是要关闭tomcat服务,都是要去到tomcat安装目录下的bin路径,当然你要是电脑关机自然是不需要的. 但最近在启动后发现了一个问题:Centos服务器,本地和服务器ip互p ...

  8. idea tomcat启动成功但是访问方面都是404_IDEA相关配置【集成Tomcatamp;项目部署】...

    "知其然知其所以然"始终是Brick我学习新兴技术的出发点,那么咱们来聊聊以下几个问题 问题1:在编写完web项目之后,我们怎么才能运行项目呢? --需要部署项目到Tomcat上. ...

  9. tomcat启动卡住

    新部署的项目启动tomcat后一直停在org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Ap ...

最新文章

  1. java8 无符号_Java8包装类 新增 无符号运算方法
  2. Oracle和Mysql的 != 差异
  3. 当向后台插入或读取JSON数据遇见回车时
  4. 【网络安全】Agent内存马的自动分析与查杀
  5. html怎么使背景图片充屏,css如何使div背景图片填充
  6. System.getProperty()参数
  7. JavaScript学习笔记:数组reduce()和reduceRight()方法
  8. JavaScript JSON数据格式
  9. linux 下网站压力测试工具webbench
  10. 触屏西门子plc和计算机通讯,西门子S7-200CPU之间及它们与触摸屏之间数据读取如何连接?...
  11. pdcp层的作用_LTE协议栈总体架构、PDCP层及RLC层概述
  12. 8个成语接龙首尾相连_八拜为交成语接龙
  13. consume(consume名词)
  14. 关于iPad程序如何强制横屏
  15. ngnix配置cgi和fastcgi
  16. 如何使用ReadProcessMemory读取多重指针
  17. C语言margin的作用是,css中margin是什么意思,margin作用是什么
  18. python修改zip文件内容_python操作zip文件
  19. 数据库 —— mycat 代理
  20. 有苦有乐的算法 --- 一个int类型的数,换成二进制后,提取最右侧的1所在位置

热门文章

  1. 金字塔图案——Java
  2. linux vmware文件互传,Linux与Windows文件互传(VMWare)
  3. SAP PS 第2节 项目状态及字段选择
  4. 聊聊 C++ 中的四种类型转换符
  5. 撤销commit操作
  6. 关于如何用WORD实现图片转文字
  7. 华为p60pro和mate50pro哪个好 华为p60pro和mate50pro参数对比
  8. O2O模式为什么这么火
  9. 关于含税单价和不含税单价的关系记录
  10. python代码画玫瑰花_python绘制玫瑰