preempt_delay 是主节点恢复后延迟接管流量的机制,需配合 track_script 健康检查使用,延迟时间应匹配服务就绪耗时(如 nginx 60~120 秒、java 应用 180~300 秒),并避免 advert_int 过小、fall 过大或 vrrp_strict 开启导致失效。

主节点恢复后立即抢回 VIP,容易引发服务抖动——Nginx 还没加载完配置、数据库连接池尚未重建、应用缓存未热身,此时切回会导致请求失败或超时。preempt_delay 不是“禁止切换”,而是让主节点“等一等、稳一稳”,再接管流量。
理解 preempt_delay 的触发时机
它只在主节点从故障状态恢复后生效,前提是:
– 节点已重新加入 VRRP 组(即 keepalived 进程重启或网络恢复)
– 当前角色为 BACKUP(因之前故障让出了 MASTER)
– 配置中未启用 nopreempt(否则 preempt_delay 不起作用)
一旦满足条件,该节点不会立刻发起抢占,而是启动倒计时,在此期间持续运行 track_script 健康检查。
设置合理的延迟时间
延迟值不是越长越好,需匹配实际服务就绪耗时。常见参考:
- Nginx + 静态资源:60~120 秒(重载配置、预热 worker 进程)
- Java 应用(Spring Boot):180~300 秒(JVM 启动、类加载、连接池填充、健康端点就绪)
- MySQL 代理或中间件:90~150 秒(连接重建、权限校验、会话同步)
建议先通过手动模拟主节点重启,观察服务真正可响应业务请求所需时间,再加 20% 缓冲作为 preempt_delay 值。
必须配合 track_script 使用
preempt_delay 自身不判断服务是否可用,它只是“计时器”。真正的健康决策靠 track_script:
- 脚本返回 0:表示服务正常,倒计时继续
- 脚本返回非 0:优先级被动态调低(如 weight -30),导致即使倒计时结束也不满足抢占条件
- 若倒计时中连续多次失败,整个等待过程会被中止,节点保持 BACKUP 状态
例如配置:
vrrp_script chk_app {<br> script "/opt/bin/check-health.sh"<br> interval 5<br> fall 3<br> rise 2<br>}
搭配
track_script { chk_app weight 20 },就能实现“延迟+动态权重”的双重保险。
避免与其他参数冲突
以下配置易导致预期失效,需特别注意:
- advert_int 设置过小(如 0.5 秒):可能使 BACKUP 节点误判 MASTER 心跳丢失,提前触发选举,干扰 preempt_delay 流程
- fall 值过大(如 fall 10):健康检查反应迟钝,即使服务已挂,节点仍维持高优先级,延迟切回失去意义
- 未关闭 vrrp_strict:该模式下不支持单播和部分认证方式,若网络环境依赖单播通信,启用 strict 会导致心跳中断,进而反复触发切换
推荐生产环境使用:advert_int 1; fall 3; rise 2; vrrp_strict off,兼顾稳定性与响应速度。










