Keepalived可通过外部脚本结合jstat检测Java堆内存使用率实现高可用切换:脚本定期获取堆使用率,超阈值(如85%)时返回非零退出码,触发Keepalived降级优先级并漂移VIP。

Keepalived 本身不直接监控 Java 进程的堆内存,它只做网络层高可用(VRRP 虚拟 IP 漂移),但可以通过外部脚本+健康检查机制,将 JVM 堆使用率作为切换依据。核心思路是:让 Keepalived 定期执行一个检测脚本,该脚本读取 Java 进程的堆内存使用情况(如通过 JMX 或 jstat),当超过阈值时主动退出非零状态,触发 Keepalived 将本节点降级为 BACKUP。
获取 Java 进程堆内存使用率
推荐用 jstat(无需开启 JMX,轻量可靠)获取实时堆使用数据:
- 先确认 Java 进程 PID:
pgrep -f "YourApplication.jar"或ps aux | grep java - 用 jstat 获取老年代/整个堆使用率:
jstat -gc <pid> | awk 'NR==2 {printf "%.0f", ($7+$8)/($10+$11)*100}'
(示例:输出85表示老年代 + 年轻代已用占比约 85%) - 若需更精确控制(如仅看老年代是否 >90%),可调整 awk 表达式,例如:
jstat -gc $PID | awk 'NR==2 {if ($8/$11*100 > 90) exit 1; else exit 0}'
编写 Keepalived 可调用的健康检查脚本
保存为 /opt/scripts/check_jvm_heap.sh,并赋予可执行权限(chmod +x):
#!/bin/bash
APP_PID=$(pgrep -f "myapp.jar" | head -n1)
if [ -z "$APP_PID" ]; then
exit 2 # 进程不存在,视为严重故障
fi
HEAP_USAGE=$(jstat -gc "$APP_PID" 2>/dev/null | awk 'NR==2 {printf "%.0f", ($7+$8)/($10+$11)*100}')
if [ -z "$HEAP_USAGE" ] || [ "$HEAP_USAGE" -gt 85 ]; then
exit 1 # 超过 85%,触发降级
else
exit 0 # 正常
fi
注意:脚本必须返回标准退出码(0=健康,非0=异常),Keepalived 仅依赖此判断。
立即学习“Java免费学习笔记(深入)”;
在 keepalived.conf 中集成该检查
在 vrrp_instance 块内添加 track_script,并定义对应脚本:
vrrp_script chk_jvm_heap {
script "/opt/scripts/check_jvm_heap.sh"
interval 5 # 每 5 秒执行一次
weight -20 # 失败时降低本节点优先级 20(避免频繁抖动)
fall 3 # 连续失败 3 次才判定异常
rise 2 # 连续成功 2 次才恢复
}
<p>vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
track_script {
chk_jvm_heap
}
virtual_ipaddress {
192.168.1.100/24 dev ens33
}
}
关键点:
– weight -20 是预防性切换的核心——当堆过高时,优先级从 100 降至 80,低于 Backup 节点(如设为 90),自动触发 VIP 漂移;
– 不建议直接用 state BACKUP 强制切换,应靠优先级动态调整,保障平滑过渡。
补充建议与验证要点
确保实际生效前完成以下检查:
- 脚本在 Keepalived 用户(通常是 root)环境下能手动运行并正确返回 0/1
- Java 进程启动用户与脚本执行用户一致,或 jstat 对目标进程有读权限(必要时加
sudo -u appuser jstat...) - Keepalived 日志(
journalctl -u keepalived -f)中能看到类似Track script chk_jvm_heap failed和priority changed记录 - 模拟高内存场景测试:用
jmap -histo:live <pid>或压力工具触发 OOM 前堆飙升,观察 VIP 是否在几秒内漂移到 Backup 节点


















