
Tomcat 服务频繁崩溃排查方法
当Tomcat服务频繁崩溃时,可以按照以下步骤进行系统化排查:
1. 检查日志文件
**关键日志位置**:
-
`catalina.out` (标准输出和错误)
-
`catalina.log` (主日志)
-
`localhost.log` (应用相关日志)
-
`host-manager.log` 和 `manager.log` (管理相关日志)
**重点关注**:
-
崩溃前的错误堆栈(Stack Trace)
-
OutOfMemoryError 或其他内存相关错误
-
线程死锁(Deadlock)信息
-
频繁的GC日志
2. 内存问题排查
**常见内存问题**:
-
堆内存溢出(Java heap space)
-
永久代/元空间溢出(PermGen/Metaspace)
-
栈溢出(StackOverflowError)
-
直接内存溢出(Direct buffer memory)
**排查工具**:
- 在启动脚本中添加JVM参数:
```
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof
```
- 使用`jmap`生成堆转储:
```bash
jmap -dump:format=b,file=/path/to/dump.hprof <pid>
```
- 使用`jstat`监控内存使用:
```bash
jstat -gcutil <pid> 1000
```
3. 线程问题排查
**检查线程状态**:
```bash
jstack <pid> > thread_dump.txt
```
分析线程转储文件,查找:
-
死锁(deadlock)
-
大量线程阻塞(blocked)
-
线程卡在相同代码位置
4. 资源泄漏检查
**常见泄漏源**:
-
数据库连接未关闭
-
文件流未关闭
-
静态集合持续增长
-
缓存未设置上限
**排查方法**:
-
使用`jmap -histo:live <pid>`查看对象分布
-
使用VisualVM或MAT分析堆转储
5. 系统资源检查
```bash
检查系统内存
free -m
检查打开文件限制
ulimit -a
检查进程资源使用
top -p <pid>
```
6. 配置检查
**关键配置项**:
-
`server.xml`中的连接器(Connector)配置
-
线程池配置
-
JVM内存参数(Xms, Xmx, PermSize/MetaspaceSize)
-
检查是否有过多的web应用部署
7. 监控工具
-
**VisualVM**:图形化监控JVM状态
-
**JConsole**:JMX监控工具
-
**Prometheus + Grafana**:建立长期监控
-
**APM工具**:如SkyWalking, Pinpoint等
8. 常见解决方案
- **内存不足**:
-
增加JVM堆大小(-Xms, -Xmx)
-
调整新生代/老年代比例(-XX:NewRatio)
-
增加元空间大小(-XX:MetaspaceSize)
- **线程问题**:
-
调整线程池大小(maxThreads)
-
优化代码避免死锁
-
减少同步块范围
- **资源泄漏**:
-
确保所有资源正确关闭
-
使用try-with-resources语句
-
限制缓存大小
- **系统限制**:
-
增加最大文件描述符数
-
调整系统内核参数
9. 高级排查
对于难以复现的问题:
-
启用飞行记录(JFR):`-XX:+FlightRecorder`
-
使用async-profiler进行性能分析
-
考虑使用商业分析工具如YourKit
通过以上系统化排查,通常可以定位到Tomcat频繁崩溃的根本原因。