熔断器的三个状态怎么转换?半开状态该放行多少个探测请求?手写的状态机和 gobreaker 一不一样?下游恢复了但不稳定时,半开放得越多是越好还是越糟?这篇用本机的小服务和 gobreaker 量出来。
时刻 | 从 | 到 --------+-----------+---------- 703 ms | closed | open 1759 ms | open | half-open 1759 ms | half-open | open 2810 ms | open | half-open 2901 ms | half-open | closed 4201 ms | closed | open 5252 ms | open | half-open 5252 ms | half-open | open 6310 ms | open | half-open 6402 ms | half-open | closed 160 次调用里:真正到达下游 80 次(其中失败 12 次),被熔断器直接拒绝 80 次,半开状态因放行名额用完被拒 0 次
连续失败打开,到期后第一个请求触发半开,半开里连续成功才关闭,失败一次就重新打开。
# | 手写:转换 | 时刻 | gobreaker:转换 | 时刻 ---+--------------------+---------+--------------------+-------- 1 | closed → open | 703 ms | closed → open | 702 ms 2 | open → half-open | 1759 ms | open → half-open | 1752 ms 3 | half-open → open | 1759 ms | half-open → open | 1752 ms 4 | open → half-open | 2810 ms | open → half-open | 2802 ms 5 | half-open → closed | 2901 ms | half-open → closed | 2902 ms 6 | closed → open | 4201 ms | closed → open | 4200 ms 7 | open → half-open | 5252 ms | open → half-open | 5252 ms 8 | half-open → open | 5252 ms | half-open → open | 5252 ms 9 | open → half-open | 6310 ms | open → half-open | 6302 ms 10 | half-open → closed | 6402 ms | half-open → closed | 6402 ms 转换序列完全相同(10 次对 10 次);gobreaker:到达下游 80 次(失败 12),拒绝(打开)80,拒绝(半开名额用完)0;手写:到达 80(失败 12),拒绝(打开)80,拒绝(半开名额用完)0
同一个剧本下,两边的转换序列完全相同,时刻差在 10 ms 以内。
半开放行数 | 打开的次数 | 进入半开的次数 | 到达下游的请求 | 半开期间到达下游的失败 | 被拒(打开) | 被拒(半开名额用完) ------+-------+---------+---------+-------------+--------+----------- 1 | 3 | 3 | 1720 | 2 | 2295 | 20 3 | 3 | 3 | 1731 | 6 | 2276 | 27 10 | 3 | 3 | 1761 | 18 | 2270 | 7 (连接类错误 0 次;不是超时,应为 0)
下游仍不可用时,每次半开都要让 N 个请求去试;放行越多,下游多挨的越多。
下游成功率 | 半开放行 1 | 半开放行 3 | 半开放行 10 ---------+----------------------------------------+-----------------------------------------+------------------------------------------- q = 100% | 中位数 0.00 s / p90 0.00 s / 平均重新打开 0.0 次 | 中位数 0.10 s / p90 0.10 s / 平均重新打开 0.0 次 | 中位数 0.45 s / p90 0.45 s / 平均重新打开 0.0 次 q = 90% | 中位数 0.00 s / p90 1.00 s / 平均重新打开 0.1 次 | 中位数 0.10 s / p90 1.20 s / 平均重新打开 0.4 次 | 中位数 1.80 s / p90 6.85 s / 平均重新打开 2.0 次 q = 70% | 中位数 0.00 s / p90 1.00 s / 平均重新打开 0.4 次 | 中位数 1.15 s / p90 5.50 s / 平均重新打开 2.0 次 | 中位数 25.33 s / p90 81.73 s / 平均重新打开 32.0 次 q = 50% | 中位数 0.00 s / p90 3.10 s / 平均重新打开 1.0 次 | 中位数 5.42 s / p90 18.55 s / 平均重新打开 7.4 次 | 中位数 ≥ 599 s / p90 ≥ 599 s / 平均重新打开 430.9 次 半开要连续 N 个成功才关闭,所以下游成功率 q 不高时,N 越大越容易在半开里又失败一次、重新打开(q^N 是一轮半开通过的概率)
要连续 N 个成功才关闭,下游成功率不高时 N 越大越难关上。