第443集Tomcat监控与JVM监控实战
Tomcat监控与JVM监控实战
1. 概述
1.1 Tomcat监控的重要性
Tomcat监控是运维工作的核心环节,通过监控可以及时发现性能瓶颈、内存泄漏、线程死锁等问题,保障应用稳定运行。Tomcat作为Java应用服务器,其监控主要关注JVM内存、线程、GC(垃圾回收)等关键指标。
监控的价值:
- 性能优化:发现性能瓶颈,优化应用性能
- 故障预防:提前发现潜在问题,避免故障发生
- 资源管理:合理分配服务器资源
- 问题定位:快速定位和解决生产问题
1.2 JVM监控工具
JDK自带监控工具:
- JConsole:图形化监控工具,简单易用
- VisualVM:功能强大的可视化监控工具
- jstat:命令行GC统计工具
- jmap:内存映射工具
- jstack:线程堆栈工具
- jinfo:JVM配置信息工具
第三方监控工具:
- JProfiler:商业性能分析工具
- YourKit:Java性能分析工具
- MAT:内存分析工具
- Prometheus + Grafana:监控指标收集和可视化
1.3 本文内容结构
本文将从以下几个方面详细介绍Tomcat和JVM监控:
- JMX监控基础:JMX原理和配置方式
- 无密码JMX监控:简单快速的监控配置
- 有密码JMX监控:安全的监控配置
- JConsole监控:使用JConsole进行监控
- VisualVM监控:使用VisualVM进行监控
- JVM命令行监控:jstat、jmap、jstack等工具
- 监控指标分析:关键指标解读和优化建议
- 生产环境监控方案:企业级监控实践
2. JMX监控基础
2.1 JMX简介
JMX(Java Management Extensions)是Java平台的管理和监控标准,提供了管理和监控Java应用程序的标准方法。通过JMX,可以监控JVM的内存、线程、GC等运行时信息。
JMX架构:
- MBean:管理Bean,暴露管理接口
- MBeanServer:MBean服务器,管理MBean
- Connector:连接器,提供远程访问
- Protocol Adapter:协议适配器,支持不同协议
2.2 JMX监控方式
本地监控:
- 监控同一台机器上的Java应用
- 无需额外配置
- 直接连接本地进程
远程监控:
- 监控远程服务器上的Java应用
- 需要配置JMX参数
- 支持无密码和有密码两种方式
2.3 JMX端口说明
JMX端口:
- JMX端口:用于JMX连接(默认9999)
- RMI端口:用于RMI通信(随机分配,可固定)
端口配置:
com.sun.management.jmxremote.port:JMX连接端口com.sun.management.jmxremote.rmi.port:RMI端口(可选)
3. 无密码方式JMX监控
3.1 配置说明
无密码方式适合内网环境或测试环境,配置简单,但安全性较低。
3.2 修改Tomcat配置
3.2.1 编辑catalina.sh
1 | # 编辑Tomcat启动脚本 |
3.2.2 添加JMX参数
在catalina.sh文件中找到JAVA_OPTS配置位置,添加以下参数:
1 | # 设置JVM内存参数 |
完整配置示例:
1 | # 在catalina.sh文件开头或JAVA_OPTS定义处添加 |
参数说明:
| 参数 | 说明 | 示例值 |
|---|---|---|
-Xms |
初始堆内存 | 128m |
-Xmx |
最大堆内存 | 1024m |
-Xss |
线程栈大小 | 1024K |
-XX:PermSize |
永久代初始大小 | 512m |
-XX:MaxPermSize |
永久代最大大小 | 512m |
-Dcom.sun.management.jmxremote |
启用JMX远程监控 | - |
-Dcom.sun.management.jmxremote.port |
JMX端口 | 12345 |
-Dcom.sun.management.jmxremote.ssl |
是否使用SSL | false |
-Dcom.sun.management.jmxremote.authenticate |
是否需要认证 | false |
-Djava.rmi.server.hostname |
RMI服务器主机名 | 192.168.6.13 |
注意:
java.rmi.server.hostname必须设置为服务器的实际IP地址- 如果使用域名,确保客户端能够解析该域名
- 生产环境建议使用有密码方式
3.3 启动Tomcat
1 | # 启动Tomcat |
验证输出:
1 | tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN 12345/java |
3.4 防火墙配置
1 | # CentOS 7+ 使用firewalld |
3.5 使用JConsole连接
3.5.1 下载和安装JDK
Windows系统:
- 下载地址:https://www.oracle.com/java/technologies/downloads/
- 推荐版本:JDK 8或JDK 11
- 安装后JConsole位于:
%JAVA_HOME%\bin\jconsole.exe
Linux系统:
- 通常JDK已安装,JConsole位于:
$JAVA_HOME/bin/jconsole
3.5.2 启动JConsole
Windows:
1 | # 方式1:直接运行 |
Linux:
1 | # 如果有图形界面 |
3.5.3 连接远程Tomcat
连接步骤:
启动JConsole
- 打开JConsole工具
选择远程连接
- 选择”远程进程”标签
- 输入连接地址:
192.168.6.13:12345 - 点击”连接”
开始监控
- 连接成功后,可以看到监控界面
- 包含:概览、内存、线程、类、VM摘要、MBean等标签
连接地址格式:
1 | 服务器IP:JMX端口 |
3.6 JConsole监控界面说明
3.6.1 概览(Overview)
显示内容:
- 堆内存使用情况
- 线程数
- 类加载数
- CPU使用率
3.6.2 内存(Memory)
监控指标:
- 堆内存:Eden、Survivor、Old Generation
- 非堆内存:Metaspace、Code Cache等
- 内存使用趋势图
关键指标:
- 堆内存使用率
- GC频率和耗时
- 内存泄漏检测
3.6.3 线程(Threads)
监控指标:
- 活动线程数
- 峰值线程数
- 线程状态分布
- 线程详细信息
关键指标:
- 线程死锁检测
- 线程等待情况
- 线程CPU使用率
3.6.4 类(Classes)
监控指标:
- 已加载类数
- 已卸载类数
- 类加载趋势
3.6.5 VM摘要(VM Summary)
显示内容:
- JVM版本信息
- 运行时间
- 线程统计
- 内存统计
- 系统属性
3.6.6 MBean
功能:
- 查看和操作MBean
- 修改JVM参数(部分)
- 触发GC
- 查看详细信息
4. 有密码方式JMX监控
4.1 配置说明
有密码方式适合生产环境,提供安全认证,防止未授权访问。
4.2 JDK管理文件说明
JDK管理文件位置:
1 | $JAVA_HOME/jre/lib/management/ |
文件说明:
jmxremote.access:用户名-权限文件jmxremote.password.template:密码文件模板jmxremote.password:密码文件(需要创建)management.properties:管理配置文件
4.3 配置步骤
4.3.1 复制密码模板文件
1 | # 进入JDK管理目录 |
权限说明:
- 密码文件必须设置为600权限(仅所有者可读写)
- 否则JMX会拒绝使用该文件
4.3.2 配置用户权限
编辑jmxremote.access文件:
1 | vim $JAVA_HOME/jre/lib/management/jmxremote.access |
添加用户权限(文件末尾追加):
1 | # 用户名 权限 |
权限类型:
readonly:只读权限,只能查看监控信息readwrite:读写权限,可以查看和修改配置create:创建权限(通常不需要)
完整配置示例:
1 | # 文件格式:用户名 权限1,权限2,... |
4.3.3 配置用户密码
编辑jmxremote.password文件:
1 | vim $JAVA_HOME/jre/lib/management/jmxremote.password |
添加用户密码(文件末尾追加):
1 | # 用户名 密码 |
完整配置示例:
1 | # 文件格式:用户名 密码 |
安全建议:
- 使用强密码
- 定期更换密码
- 限制密码文件访问权限
4.3.4 修改Tomcat配置
编辑catalina.sh:
1 | vim /application/tomcat/bin/catalina.sh |
添加JMX参数:
1 | # 设置JVM内存参数 |
完整配置示例:
1 | JAVA_OPTS="$JAVA_OPTS \ |
4.3.5 启动Tomcat
1 | # 启动Tomcat |
4.4 使用JConsole连接
4.4.1 连接步骤
启动JConsole
- 打开JConsole工具
选择远程连接
- 选择”远程进程”标签
- 输入连接地址:
192.168.6.13:12345 - 点击”连接”
输入用户名和密码
- 弹出认证对话框
- 输入用户名:
admin - 输入密码:
123456 - 点击”确定”
开始监控
- 连接成功后,可以查看监控信息
- 根据用户权限,可以查看或修改配置
4.5 权限验证
只读用户(admin):
- 可以查看所有监控信息
- 不能修改JVM配置
- 不能触发GC
读写用户(monitor):
- 可以查看所有监控信息
- 可以修改部分JVM配置
- 可以触发GC
5. Java VisualVM监控
5.1 VisualVM简介
VisualVM是JDK自带的图形化监控工具,功能比JConsole更强大,提供了更丰富的监控和分析功能。
VisualVM特性:
- 多应用监控:同时监控多个Java应用
- 性能分析:CPU和内存性能分析
- 线程分析:线程转储和分析
- 堆转储:生成和分析堆转储文件
- 插件扩展:支持插件扩展功能
5.2 启动VisualVM
5.2.1 Windows系统
1 | # 方式1:直接运行 |
5.2.2 Linux系统
1 | # 如果有图形界面 |
5.3 添加JMX连接
5.3.1 添加远程连接
步骤:
打开VisualVM
- 启动VisualVM工具
添加JMX连接
- 菜单:
文件→添加JMX连接... - 或右键左侧面板 →
添加JMX连接...
- 菜单:
输入连接信息
- 连接:
192.168.6.13:12345 - 显示名称:
Tomcat-生产环境(可选) - 如果使用密码认证,会弹出认证对话框
- 连接:
连接
- 点击”确定”连接
5.3.2 连接地址格式
1 | 服务器IP:JMX端口 |
5.4 VisualVM监控功能
5.4.1 概览(Overview)
显示内容:
- JVM版本和参数
- 系统属性
- 运行时间
- 进程ID
5.4.2 监视(Monitor)
监控指标:
- CPU使用率:实时CPU使用情况
- 堆内存:堆内存使用趋势
- Metaspace:元空间使用情况
- 类:已加载类数
- 线程:活动线程数
功能:
- 实时图表显示
- 数据导出
- 性能分析
5.4.3 线程(Threads)
功能:
- 线程列表:查看所有线程
- 线程状态:运行、等待、阻塞等
- 线程转储:生成线程转储文件
- 线程时间线:线程活动时间线
线程分析:
- 检测死锁
- 查看线程堆栈
- 分析线程等待情况
5.4.4 采样器(Sampler)
功能:
- CPU采样:分析CPU使用情况
- 内存采样:分析内存使用情况
采样分析:
- 热点方法
- 内存分配
- 对象创建
5.4.5 Profiler(性能分析器)
功能:
- CPU性能分析:分析CPU使用热点
- 内存性能分析:分析内存分配
注意:
- Profiler功能需要安装插件
- 可能影响应用性能
5.4.6 堆转储(Heap Dump)
功能:
- 生成堆转储:生成堆内存快照
- 分析堆转储:分析内存使用情况
- 查找内存泄漏:定位内存泄漏问题
使用场景:
- 内存泄漏分析
- 内存使用优化
- 对象分布分析
5.5 VisualVM插件
5.5.1 安装插件
步骤:
打开插件管理器
- 菜单:
工具→插件
- 菜单:
可用插件
- 浏览可用插件
- 选择需要的插件
安装插件
- 点击”安装”
- 等待安装完成
常用插件:
- Visual GC:GC可视化
- Threads Inspector:线程检查器
- MBeans Browser:MBean浏览器
6. JVM命令行监控工具
6.1 jstat - GC统计工具
6.1.1 基本用法
1 | # 查看GC统计信息 |
输出说明:
1 | S0 S1 E O M CCS YGC YGCT FGC FGCT GCT |
列说明:
S0:Survivor 0使用率S1:Survivor 1使用率E:Eden区使用率O:Old区使用率M:Metaspace使用率CCS:压缩类空间使用率YGC:Young GC次数YGCT:Young GC总耗时FGC:Full GC次数FGCT:Full GC总耗时GCT:GC总耗时
6.1.2 常用选项
1 | # 查看堆内存使用情况 |
6.2 jmap - 内存映射工具
6.2.1 查看堆内存
1 | # 查看堆内存使用情况 |
6.2.2 生成堆转储
1 | # 生成堆转储文件 |
堆转储分析:
- 使用MAT(Memory Analyzer Tool)分析
- 使用jhat分析(JDK自带)
- 使用VisualVM分析
6.2.3 查看对象统计
1 | # 查看对象实例统计 |
6.3 jstack - 线程堆栈工具
6.3.1 生成线程转储
1 | # 生成线程转储 |
6.3.2 检测死锁
1 | # 生成线程转储并检测死锁 |
6.3.3 线程状态分析
线程状态:
RUNNABLE:运行中BLOCKED:阻塞WAITING:等待TIMED_WAITING:定时等待
分析命令:
1 | # 统计线程状态 |
6.4 jinfo - JVM配置信息
6.4.1 查看JVM参数
1 | # 查看所有JVM参数 |
6.4.2 修改JVM参数(部分)
1 | # 启用GC日志 |
注意:
- 只能修改部分JVM参数
- 大部分参数需要在启动时设置
6.5 综合监控脚本
1 | cat > /usr/local/bin/jvm_monitor.sh << 'EOF' |
7. 监控指标分析
7.1 内存监控指标
7.1.1 堆内存指标
关键指标:
- 堆内存使用率:应保持在70%以下
- Eden区使用率:监控Young GC频率
- Old区使用率:监控Full GC频率
- Metaspace使用率:监控类加载情况
告警阈值:
- 堆内存使用率 > 80%:警告
- 堆内存使用率 > 90%:严重告警
- Full GC频率 > 1次/分钟:警告
7.1.2 内存泄漏检测
检测方法:
- 趋势分析:堆内存持续增长
- GC分析:Full GC后内存不释放
- 堆转储分析:分析堆转储文件
分析工具:
- MAT(Memory Analyzer Tool)
- VisualVM堆转储分析
- jhat(JDK自带)
7.2 GC监控指标
7.2.1 GC频率
正常范围:
- Young GC:几秒到几分钟一次
- Full GC:几分钟到几十分钟一次
异常情况:
- Young GC频率过高:Eden区过小或对象创建过快
- Full GC频率过高:内存不足或内存泄漏
7.2.2 GC耗时
正常范围:
- Young GC:< 100ms
- Full GC:< 1s
异常情况:
- GC耗时过长:堆内存过大或GC算法不当
- Full GC频繁:需要优化内存配置
7.2.3 GC优化建议
优化策略:
- 调整堆内存大小
- 选择合适的GC算法(G1、Parallel、CMS)
- 优化对象创建:减少临时对象
- 优化代码:避免内存泄漏
7.3 线程监控指标
7.3.1 线程数量
关键指标:
- 活动线程数:监控线程数量
- 峰值线程数:监控线程峰值
- 线程创建速率:监控线程创建情况
告警阈值:
- 活动线程数 > 1000:警告
- 线程创建速率过快:警告
7.3.2 线程状态
关键指标:
- 运行线程:CPU使用情况
- 等待线程:I/O等待情况
- 阻塞线程:锁竞争情况
异常情况:
- 大量线程等待:可能存在性能瓶颈
- 线程死锁:需要立即处理
7.4 CPU监控指标
7.4.1 CPU使用率
关键指标:
- 进程CPU使用率:监控进程CPU占用
- 线程CPU使用率:定位CPU热点
告警阈值:
- CPU使用率 > 80%:警告
- CPU使用率 > 95%:严重告警
7.4.2 CPU热点分析
分析方法:
- VisualVM CPU采样
- JProfiler CPU分析
- jstack线程分析
8. 生产环境监控方案
8.1 监控架构
监控架构图:
1 | Tomcat应用 |
8.2 Prometheus + JMX Exporter
8.2.1 安装JMX Exporter
1 | # 下载JMX Exporter |
8.2.2 配置Tomcat
1 | # 在catalina.sh中添加 |
8.2.3 Prometheus配置
1 | # prometheus.yml |
8.3 监控告警规则
8.3.1 内存告警
1 | # Prometheus告警规则 |
8.3.2 GC告警
1 | - alert: TomcatFullGCFrequent |
8.4 监控最佳实践
- 多维度监控:内存、线程、GC、CPU
- 历史数据:保留至少30天历史数据
- 告警规则:设置合理的告警阈值
- 自动化处理:配置自动重启、扩容等
- 定期分析:定期分析监控数据,优化配置
9. 故障排查案例
9.1 案例1:内存泄漏
现象:
- 堆内存持续增长
- Full GC频繁
- 应用响应变慢
排查步骤:
1 | # 1. 查看堆内存使用趋势 |
解决方案:
- 修复内存泄漏代码
- 增加堆内存大小(临时)
- 优化对象创建
9.2 案例2:线程死锁
现象:
- 应用无响应
- CPU使用率低
- 线程数正常
排查步骤:
1 | # 1. 生成线程转储 |
解决方案:
- 修复死锁代码
- 调整锁顺序
- 使用超时锁
9.3 案例3:CPU占用高
现象:
- CPU使用率持续100%
- 应用响应慢
排查步骤:
1 | # 1. 查看CPU使用情况 |
解决方案:
- 优化热点代码
- 减少循环计算
- 使用缓存
10. 总结
10.1 核心要点
- JMX监控:无密码和有密码两种方式
- 监控工具:JConsole、VisualVM、命令行工具
- 监控指标:内存、GC、线程、CPU
- 故障排查:使用监控工具快速定位问题
- 生产实践:Prometheus + Grafana监控方案
10.2 架构师建议
监控设计:
- 多维度监控
- 历史数据保留
- 告警规则设计
工具选择:
- 开发环境:JConsole、VisualVM
- 生产环境:Prometheus + Grafana
- 故障排查:命令行工具
优化策略:
- 定期分析监控数据
- 根据监控数据优化配置
- 建立监控告警机制
10.3 学习路径
- 基础监控:JConsole、VisualVM使用
- 命令行工具:jstat、jmap、jstack
- 指标分析:理解关键监控指标
- 故障排查:掌握故障排查方法
- 生产实践:Prometheus监控方案
相关文章:


