Tomcat作为的Java Web应用服务器之一,在企业环境中被广泛使用。然而,许多运维人员和开发者都曾遇到过Tomcat服务
假死的情况——进程虽然仍在运行,但却无法处理任何请求,也不会返回有效的错误响应。本文将深入分析Tomcat假死的主要原因,并提供系统的排查方法和解决方案。
1 什么是Tomcat假死?
Tomcat假死是指服务
进程仍然存在,但无法正常响应请求的状态。通常表现为:
-
客户端浏览器访问时长时间加载无结果
-
无法返回4xx或5xx等HTTP错误码
-
服务器CPU和内存使用率可能正常
-
重启Tomcat后服务恢复正常
2 Tomcat假死的主要原因
Tomcat假死通常由以下几个方面的问题引起。
2.1 内存不足与GC问题
内存溢出是导致Tomcat假死的常见原因,尤其是堆内存不足:
# 查看Tomcat内存使用情况jstat -gcutil <pid> 1000
当频繁出现Full GC(FGC列数值高)或抛出
java.lang.OutOfMemoryError: Java heap space错误时
,应用性能会急剧下降直至完全假死。
2.2 线程池耗尽
Tomcat默认
最大线程数为200
。当并发请求数超过此限制时,新请求会被放入等待队列,但如果等待队列也已满(默认100),后续请求将被拒绝,可能导致服务不可用。
<!-- conf/server.xml 中的连接器配置 --><Connector
executor="tomcatThreadPool"
maxThreads="200"
minSpareThreads="20"
acceptCount="100"/>
2.3 死锁(Deadlock)
高并发场景下,线程死锁是Tomcat假死的一个重要原因
。特别是Tomcat 9.0.26版本在高并发下存在已知的DeadLock问题
。死锁可能发生在:
使用jstack工具可以检测死锁:
# 生成线程转储并检查死锁jstack -F <pid> > thread_dump.loggrep -i "deadlock" thread_dump.log
2.4 数据库连接池问题
数据库连接泄漏或配置不当也会导致Tomcat假死:
-
连接池最大连接数设置过高导致数据库资源耗尽
-
连接未正确关闭导致泄漏
-
长时间运行的事务占用连接
2.5 文件描述符耗尽
Linux系统默认的文件描述符限制可能无法满足高并发需求,导致
Too many open files错误
。
2.6 网络连接问题
大量的CLOSE_WAIT状态连接是Tomcat假死的一个常见征兆
,通常表明应用程序没有正确关闭连接。
HTTP/1.1默认使用长连接,每个连接的生命周期默认长达2小时(7200秒)
。如果连接未及时关闭,可能在2小时内耗尽所有可用连接。
3 排查Tomcat假死的系统方法
当Tomcat出现假死时,可以按照以下流程系统地进行排查。
3.1 检查日志文件
首先查看Tomcat日志,寻找异常信息:
# 查看最新日志内容tail -n 100 /var/log/tomcat/catalina.out# 搜索错误和异常grep -i "error\|exception" /var/log/tomcat/catalina.out
重点关注
OutOfMemoryError、
StackOverflowError或线程死锁相关信息
。
3.2 监控系统资源
使用系统工具监控资源使用情况:
# 实时查看CPU和内存使用top -p $(pgrep -f tomcat)# 检查线程数ps -eLf | grep tomcat | wc -l# 查看磁盘空间df -h# 检查文件描述符使用lsof -p <pid> | wc -l
3.3 生成和分析线程转储
线程转储是分析死锁和线程问题的重要工具:
# 生成线程转储kill -3 <pid> # 输出到catalina.out# 或使用jstackjstack -l <pid> > thread_dump.log# 在线分析工具推荐:fastthread.io
3.4 内存分析
如果怀疑内存泄漏,可以生成堆转储文件进行分析:
# 生成堆转储jmap -dump:format=b,file=/tmp/heap.hprof <pid># 使用VisualVM或Eclipse MAT分析堆转储
4 解决方案与优化建议
4.1 内存优化
根据应用需求和服务器配置,
合理设置JVM参数:
# 在setenv.sh中设置JVM参数export JAVA_OPTS="-Xms2g -Xmx2g -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
建议:
-
Xms和
Xmx设为相同值,避免动态调整开销
-
堆大小不超过系统物理内存的70%
-
考虑使用G1GC等现代垃圾收集器
4.2 线程池优化
根据并发需求和服务器配置,
调整线程池设置:
<Connector
port="8080"
protocol="HTTP/1.1"
maxThreads="500"
minSpareThreads="20"
acceptCount="500"
connectionTimeout="20000"
redirectPort="8443"/>gov.711jrs.com
govzb.711jrs.com
vip.711jrs.com
gcdr.711jrs.com
178jrs.cn
m.178jrs.cn
wap.178jrs.cn
gov.178jrs.cn
💡 建议:
maxThreads值可根据CPU核心数调整(推荐
核心数 * 200)
4.3 死锁问题解决
4.4 连接管理
# 修改/etc/sysctl.confnet.ipv4.tcp_fin_timeout = 30net.ipv4.tcp_keepalive_time = 1800net.ipv4.tcp_keepalive_probes=2net.ipv4.tcp_keepalive_intvl=2# 重启网络服务/etc/rc.d/init.d/network restart
4.5 文件描述符限制调整
增加系统文件描述符限制:
# 修改/etc/security/limits.conftomcat soft nofile 65535tomcat hard nofile 65535
4.6 监控与预防措施
-
启用监控工具:使用JMX、Jconsole或APM工具(如SkyWalking)对Tomcat进行实时监控
-
定期维护:清理不必要的文件和缓存,提高Tomcat性能和稳定性
-
健康检查:添加启动脚本检测Tomcat状态,崩溃后自动重启
# 简单的健康检查脚本while true; do
if ! pgrep -f tomcat; then
/opt/tomcat/bin/startup.sh fi
sleep 60done
5 总结
Tomcat假死问题通常由
资源耗尽(内存、线程、文件描述符)、
代码缺陷(死锁、连接泄漏)或
配置不当引起。通过系统化的排查方法:
-
检查日志文件
-
监控系统资源
-
分析线程转储和堆转储
-
优化配置参数
可以有效地定位和解决大部分Tomcat假死问题。预防胜于治疗,合理的容量规划、定期的应用程序代码审查以及持续的性能监控,是避免Tomcat假死的关键措施。
本文综合了多个来源的信息,并结合实践经验整理了Tomcat假死的排查与解决方法。实际环境中,可能需要根据具体情况进行调整和深入分析。