咨询AWS EC2实例达内存/CPU阈值时自动生成Heap Dump的方案
自动生成Heap Dump的解决方案(内存/CPU阈值触发)
方案一:Shell脚本+JDK原生工具(适合EC2 Linux实例)
通过定时脚本监控系统内存、CPU及JVM堆使用率,达到阈值时自动调用jmap生成堆转储。
编写监控脚本
创建monitor_heap_dump.sh,替换your-java-process-name为你的Java进程名称,按需调整阈值和dump存储路径:#!/bin/bash # 获取目标Java进程ID PID=$(ps aux | grep your-java-process-name | grep -v grep | awk '{print $2}') if [ -z "$PID" ]; then exit 1 fi # 计算系统内存使用率(百分比) MEM_USAGE=$(free | grep Mem | awk '{printf "%.1f", $3/$2*100}') # 计算CPU使用率(百分比) CPU_USAGE=$(top -bn1 | grep Cpu | awk '{printf "%.1f", $2}') # 计算JVM堆内存使用率(百分比,已用堆/最大堆) HEAP_USAGE=$(jstat -gc $PID | awk 'NR==3{printf "%.1f", ($3+$4)/$2*100}') # 触发阈值(可自定义) THRESHOLD=80 # 锁文件,避免短时间内重复生成dump LOCK_FILE=/tmp/heap_dump.lock # 满足任一阈值且未锁定时生成dump if [ ! -f $LOCK_FILE ] && (echo "$MEM_USAGE >= $THRESHOLD" | bc -l | grep -q 1 || echo "$CPU_USAGE >= $THRESHOLD" | bc -l | grep -q 1 || echo "$HEAP_USAGE >= $THRESHOLD" | bc -l | grep -q 1); then touch $LOCK_FILE # 生成堆转储文件 jmap -dump:format=b,file=/var/log/heapdump_$(date +%Y%m%d_%H%M%S).hprof $PID # 1小时后自动释放锁,允许再次触发 sleep 3600 && rm -f $LOCK_FILE & fi设置定时任务
给脚本添加执行权限:chmod +x monitor_heap_dump.sh
编辑crontab:crontab -e,添加以下内容(每5分钟执行一次监控):*/5 * * * * /path/to/monitor_heap_dump.sh >> /var/log/monitor_dump.log 2>&1
方案二:JMX+Prometheus Alertmanager(适合分布式监控场景)
通过JMX暴露JVM指标,结合Prometheus监控阈值,触发Alertmanager调用脚本生成堆转储。
开启JMX远程连接
在Java进程启动参数中添加JMX配置(生产环境建议开启认证和SSL):-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false配置Prometheus监控
使用jmx_exporter采集JVM指标,配置Prometheus规则监控内存/CPU阈值,当触发时调用Alertmanager的webhook脚本。编写JMX触发dump脚本
使用jmxterm工具通过JMX调用堆转储接口:#!/bin/bash PID=$(ps aux | grep your-java-process-name | grep -v grep | awk '{print $2}') # 连接JMX并生成dump jmxterm -l localhost:9010 -e "run -b java.lang:type=Memory dumpHeap /var/log/heapdump_$(date +%Y%m%d_%H%M%S).hprof true"
注意事项
- 磁盘空间:Heap Dump文件大小接近JVM堆最大值,需确保EC2实例磁盘充足,可添加定时清理旧dump的脚本。
- STW影响:
jmap生成dump时会触发JVM停顿,生产环境需评估业务影响,可调整监控间隔或仅在非核心时段允许触发。 - 进程匹配:确保脚本能准确匹配目标Java进程,避免误操作其他进程。
内容的提问来源于stack exchange,提问作者anshul Gupta
相关产品推荐
相关产品推荐

