fail_timeout决定节点被标记为不可用后的静默观察期及时机恢复,即暂停转发时长及首次试探请求时刻;它不控制探测频率,而是靠真实请求驱动恢复,设太小易震荡、太大延缓回流。

fail_timeout 不是用来“调高检查频率”的,它决定的是节点被标记为不可用后,Nginx 主动暂停转发的时长,以及之后是否尝试恢复——换句话说,它控制的是**恢复时机**,而不是探测动作发生的频次。
fail_timeout 的真实作用是定义“静默观察期”
当某个 upstream 节点因连续失败(达到 max_fails)被标记为 down 后,Nginx 会在接下来的 fail_timeout 秒内完全跳过它,不发任何请求。到期后的**第一个新请求**才会试探性地发给该节点:若成功,则重新纳入可用池;若失败,则再次归零计数、重新开始滑动窗口统计。
- fail_timeout=10s:节点被摘除后,第 11 秒起才可能收到第一个试探请求
- fail_timeout=60s:即使节点在第 2 秒就已恢复,Nginx 也要等到第 61 秒才试一次
- 它不是周期性 ping,也不触发主动探测——纯靠真实业务请求驱动恢复
想加快恢复感知?关键不在拉短 fail_timeout,而在缩短“首次重试延迟”
真正影响恢复速度的,是 fail_timeout 值本身。但盲目缩短它有风险:
- 设得太小(如 3s),节点刚恢复就遭遇瞬时排队或 GC 暂停,一次失败又触发下线,形成震荡
- 设得太大(如 120s),故障已修复却要等两分钟才能回流,SLA 受损
- 推荐根据后端平均恢复时间设定:Redis 崩溃重启通常
配套必须做:让试探请求更快失败,避免卡住恢复节奏
如果 proxy_read_timeout 大于 fail_timeout,那么试探请求可能卡在读阶段超时,导致整个 fail_timeout 周期被无效占用,无法及时触发下一次重试。
- fail_timeout=10s 时,proxy_read_timeout 应 ≤5s,proxy_connect_timeout ≤2s
- 同时启用 proxy_next_upstream error timeout,确保连接失败、读超时能立即计入失败并推动状态更新
- 禁用 proxy_next_upstream http_502(除非你明确需要重试 502),否则缓存服务崩溃返回 502 会被反复重试其他节点,掩盖真实故障
更进一步:用主动健康检查补足被动机制的滞后性
仅靠 fail_timeout + max_fails 是被动响应,恢复依赖真实流量。对强一致性或低延迟要求高的场景,建议叠加主动检查:
- 使用 OpenResty 或 Nginx Plus 的 health_check 指令,例如:health_check interval=5s fails=2 passes=2 uri=/health;
- 主动探测不受业务请求驱动,每 5 秒固定检查一次,2 次失败即标记 down,2 次成功即恢复 —— 完全绕开 fail_timeout 的等待延迟
- 注意 /health 接口必须真实检测后端连接性(如 Redis::ping()),不能只返回 HTTP 200











