nginx 的 max_fails 和 fail_timeout 到底怎么摘除节点?什么算失败?偶发失败的节点会被怎么对待?恢复要多久?这篇用 kill 进程和返回 503 两种故障把被动健康检查逐项量出来。
故障 | 第 1 到 4 秒 client 看到的 5xx | 其中 nginx 的 connect() failed 行数 | 第 1 到 4 秒各自应答的请求(键:返回的内容或状态码)
-------------------------------------+--------------------------+--------------------------------+------------------------------
(a) A 被 kill,连接被拒 | 0 | 5 | {'B': 150}
(b) A 回 503,默认 next_upstream | 75 | 见右列 | {'503': 75, 'B': 75}
(c) A 回 503,next_upstream 含 http_503 | 0 | 见右列 | {'B': 150} 连接被拒算 error;503 默认不算,要加 http_503;不算失败就不会摘除,也不会重试。
A 的失败率 p | A 的份额 | client 看到的 5xx | A 被摘除的总时长(估计) | 摘除的次数 ---------+-------+----------------+---------------+------ 0% | 50% | 0 | 0.0 s | 0 2% | 21% | 0 | 10.5 s | 2 10% | 6% | 0 | 16.1 s | 3 30% | 2% | 0 | 17.4 s | 3 70% | 0% | 0 | 17.5 s | 1 失败率只有 2% 的节点也会被偶尔摘除:nginx 数的是 5 秒内累计 3 次失败,而 100 个/秒、一半流量给 A 时 5 秒里 A 会收到约 250 个请求,2% 就是约 5 个失败;所以只看“次数”的被动检查对高流量的节点非常敏感,对低流量的节点又很迟钝
nginx 数 fail_timeout 内的失败次数,不看比例,高流量的节点即使失败率很低也会被反复摘除。
fail_timeout | 3 次的恢复用了(故障起点 1.0 / 1.4 / 1.8 秒) | 故障期间 A 收到的失败请求的时刻(3 次,秒) -------------+----------------------------------+------------------------------------------------------------------- 2 s | 2.7 s / 2.5 s / 2.3 s | [1.0, 1.0, 1.1, 3.7] | [1.4, 1.4, 1.5, 3.9] | [1.8, 1.8, 1.9, 4.1] 5 s | 2.3 s / 3.1 s / 2.9 s | [1.0, 1.0, 1.1] | [1.4, 1.4, 1.5] | [1.8, 1.8, 1.9] 10 s | 7.9 s / 7.6 s / 7.4 s | [1.0, 1.0, 1.1] | [1.4, 1.4, 1.5] | [1.8, 1.8, 1.9] 看右列:fail_timeout 较短时,有的运行里故障期间 A 多收到了一个失败请求(摘除到期后放过去试的那个请求,A 还没恢复,试失败就再摘除一个完整的 fail_timeout);有的运行里试探恰好发生在 A 恢复之后,恢复很快。fail_timeout 越长,故障结束后越晚才重新用上 A,而且同一个 fail_timeout 下恢复用的时间随故障与摘除时刻的相位而变
摘除到期后放一个请求去试,A 仍失败就再摘除一个 fail_timeout;fail_timeout 越长恢复越晚。