CentOS 上监控 Java 应用的实用方案
一 快速定位与系统层监控
- 进程与基础资源
- 查看 Java 进程:ps -ef | grep java、jps -v、pgrep -af java
- 实时资源:top -p (按 1 展开多核)、htop(需安装)
- 系统综合:nmon(CPU、内存、磁盘 I/O、网络)、dstat -ta 1(替代 vmstat+iostat 的轻量工具)
- 磁盘与内存:df -h、free -m
- 说明:以上命令用于快速确认是否存在 CPU 飙高、内存吃紧、I/O 瓶颈 等系统层问题,为后续 JVM 层诊断提供方向。
二 JVM 层诊断工具
- 常用诊断命令(需 JDK,按 执行)
- jstat -gcutil <间隔秒> <次数>:查看 GC 次数/时间、Eden/Survivor/Old 使用率,快速判断 GC 压力
- jstack :抓取线程栈,定位 死锁、长时间 RUNNABLE/BLOCKED/WAITING
- jmap -heap :查看堆配置与使用情况;jmap -dump:format=b,file=heap.hprof 生成堆转储
- jinfo :查看/调整 JVM 参数(如堆大小、GC 策略)
- jps -v:列出 Java 进程与启动参数,便于核对 -Xms/-Xmx/-XX:+UseG1GC 等配置
- 图形化与在线诊断
- JConsole / VisualVM:通过 JMX 远程监控 内存、线程、类、CPU 等,支持 堆转储分析
- Arthas:线上诊断神器,支持 反编译、热修复、线程/方法追踪、watch/trace 等,适合生产应急
- 典型用法示例
- 持续观察 GC:jstat -gcutil 12345 2s 30
- 抓取线程栈:jstack 12345 > threads.txt
- 导出堆转储:jmap -dump:format=b,file=heap.hprof 12345
- 在线排查:java -jar arthas-boot.jar 选择 后使用 dashboard/thread/heapdump 等命令
三 指标化监控与可视化
- JMX Exporter + Prometheus + Grafana
- 以 JMX Exporter 暴露 JVM MBeans(如 Memory、Threading、GarbageCollector、ClassLoading)为 Prometheus 指标
- Prometheus 定时拉取指标,Grafana 配置 JVM 仪表盘(面板包含 Heap/Meta/Non-Heap、GC 次数/时间、线程数、类加载 等)
- 适用场景:容器化/K8s 与多实例统一采集、长期存储与告警
- 应用内埋点与 APM
- Micrometer + Prometheus:在代码中埋点(如 HTTP 延迟、业务计时、JVM 指标),对接 Prometheus/Grafana
- Spring Boot Actuator:暴露 /actuator/health、/metrics、/prometheus(配合 Micrometer)用于健康与指标
- SkyWalking / Zipkin:分布式追踪与性能分析,定位 跨服务调用链 瓶颈
- New Relic / AppDynamics:商用 APM,提供 响应时间、吞吐量、错误率、调用链 等深度分析
- 选型建议
- 需要“开箱即用 + 长期趋势”选 JMX Exporter + Prometheus/Grafana
- 需要“业务指标 + 代码级剖析”选 Micrometer/Actuator + APM
四 日志分析与告警
- 日志定位与实时查看
- 定位日志路径:结合 ps -ef | grep java 查看应用启动参数中的 -Dlogging.file= 或 catalina.out(Tomcat)
- 实时跟踪:tail -f app.log | grep “ERROR”,或按关键字/时间窗口检索
- 性能瓶颈定位
- CPU 高:top 找高占用线程 → printf “%x\n” <线程ID> → jstack 中查 nid=0x… 的栈
- 内存泄漏:jmap 导出 heap.hprof → Eclipse MAT 分析 Dominator Tree/Leak Suspects
- I/O 阻塞:线程栈中大量 WAITING on condition 或日志中 DB/HTTP 超时
- 日志治理
- 动态调整日志级别(避免生产过量日志)、优化格式(减少 MDC/堆栈 开销)
- 使用 logrotate 做 按日切分、压缩与保留策略,便于检索与归档
五 一键健康检查脚本示例
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="${1:-myapp.jar}"
PID=$(pgrep -f "$APP_NAME" | head -n1)
if [[ -z "$PID" ]]; then
echo "[ERROR] $APP_NAME is NOT running."
exit 1
fi
echo "=== $APP_NAME (PID=$PID) Health Check ==="
echo "[1/5] CPU/Memory (top):"
top -b -n1 -p "$PID" | head -n12
echo -e "\n[2/5] GC Summary (jstat):"
jstat -gcutil "$PID" 1 1
echo -e "\n[3/5] Thread Count (jstack):"
jstack "$PID" | grep -E 'java.lang.Thread.State' | sort | uniq -c
echo -e "\n[4/5] Open Files / Connections:"
ls -1 /proc/"$PID"/fd 2>/dev/null | wc -l
ss -tnp | grep -E "pid=$PID" | wc -l
echo -e "\n[5/5] Recent Errors in Logs (last 200 lines):"
LOG=$(ps -ef | grep "$APP_NAME" | grep -Eo '\-Dlogging\.file=[^ ]+' | cut -d= -f2 || echo "/var/log/$APP_NAME.log")
[[ -f "$LOG" ]] && tail -n200 "$LOG" | grep -i "ERROR" | tail -n20 || echo "Log file not found: $LOG"
- 使用方式:保存为 check_java.sh,执行 chmod +x check_java.sh && ./check_java.sh your-app.jar
- 可扩展:接入 Prometheus Node Exporter textfile、Zabbix Agent 用户参数 或 Shell 告警脚本,实现自动告警与趋势记录。