关键在于健康检查必须基于真实业务可用性(如http /healthz探测),配合vrrp秒级通告(advert_int 1)、合理优先级差(主100/备50)、nopreempt防抢vip、worker_shutdown_timeout保障平滑退出,以及arp和防火墙协同收敛。

要让 Nginx 与 Keepalived 在主备模式下实现可靠、快速的切换,关键不是堆砌参数,而是让健康判断真实反映业务就绪状态,并让网络层配合收敛。配置本身不复杂,但几处细节没调好,切换就可能卡在 5 秒以上,甚至出现脑裂或丢请求。
Keepalived 健康检查必须基于业务可用性
单纯检测 Nginx 进程是否存活(如 kill -0 $(cat /var/run/nginx.pid))远远不够——进程在、但 upstream 全挂了,或者配置重载中,服务实际已不可用。必须通过 HTTP 接口探测真实响应:
- 在 Nginx 配置中暴露轻量健康端点,例如:
location /healthz { return 200 "OK\n"; add_header Content-Type text/plain; }
确保该 location 不受限流、鉴权、rewrite 或 upstream 异常影响 - Keepalived 的
vrrp_script应调用curl -f http://127.0.0.1:80/healthz,返回非 200 即触发降级 - 设置
interval 2(每 2 秒检测一次)、fall 2(连续 2 次失败即判定故障)、rise 2(连续 2 次成功才恢复),避免偶发抖动误切
主备角色与优先级需明确且稳定
主节点设为 state MASTER,备节点为 state BACKUP;两者 virtual_router_id 必须一致,interface 名称需与实际网卡匹配(如 ens33 或 eth0):
- 主节点
priority设为 100,备节点设为 50(差值 ≥ 50),避免因网络延迟导致短暂优先级反转 - 备节点配置中启用
nopreempt,防止主节点恢复后立即抢 VIP,造成反复切换 -
advert_int 1是硬性要求——VRRP 通告间隔必须压缩到 1 秒,否则检测滞后无法满足秒级目标
Nginx 自身需支持平滑退出
Keepalived 触发切换时,若 Nginx 正在 reload 或 shutdown,旧 worker 可能被强制 kill,导致正在处理的请求中断:
- 在
nginx.conf的http块中添加:worker_shutdown_timeout 3s;—— 给 worker 3 秒时间处理完存量连接再退出 - 重启务必用
nginx -s reload,而非systemctl restart nginx,后者可能绕过平滑机制 - 健康检查脚本里若包含重启逻辑,应先调用
/usr/sbin/nginx -s reload,再等待 3 秒以上再检查状态
系统与网络层必须协同收敛
VIP 切换后客户端能否立刻访问,取决于 ARP 响应是否及时、防火墙是否放行 VIP 流量:
- 两台机器均执行:
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignoreecho 2 > /proc/sys/net/ipv4/conf/all/arp_announce
确保只有持有 VIP 的主机响应 ARP 请求 - 清掉防火墙对 VIP 的拦截规则,尤其检查 INPUT 链中是否有类似
-j DROP匹配未知源 IP 的策略 - 内网调用建议直连 VIP;若走 DNS,TTL 必须设为 ≤10 秒,否则客户端缓存会掩盖真实切换效果











