熔断、超时、重试放在一起,哪些组合会互相抵消?重试放在熔断器的里面还是外面?超时设得比下游的尾延迟还短会怎样?这篇用本机的小服务量出四个典型的配置冲突案例。
放法 | 熔断器打开 | 到达下游的逻辑请求数 | 下游收到的调用 | 被熔断器拒绝的尝试 ------------------+-------------+------------+---------+---------- 重试在熔断器里面(熔断器包着重试) | 第 5 个逻辑请求之后 | 5 | 15 | 7 重试在熔断器外面(重试包着熔断器) | 第 2 个逻辑请求之后 | 2 | 5 | 11
放在外面时每次尝试各记一次失败,熔断器打开得更快,下游挨的调用更少。
调用超时 | 20 线程:打开用了多久 | 到达下游的调用 | 被拖住的线程时间 | 1 线程:打开用了多久 | 到达下游的调用 | 被拖住的线程时间 ------+--------------+---------+----------+-------------+---------+--------- 0.2 s | 0.21 s | 24 | 4.9 s | 1.01 s | 5 | 1.0 s 1 s | 1.00 s | 24 | 24.1 s | 5.02 s | 5 | 5.0 s 3 s | 3.01 s | 24 | 72.1 s | 15.01 s | 5 | 15.0 s (连接类错误 0 次;不是超时,应为 0)
失败要等超时才记录,超时越长熔断器越晚知道,被拖住的线程时间与超时成正比。
策略 | 拿到失败的延迟中位数 | p99 ---------+------------+--------- 熔断器打开也重试 | 370.1 ms | 379.1 ms 熔断器打开就放弃 | 0.0 ms | 0.0 ms
熔断器打开是快速失败,再退避重试只会白等。
调用超时 | 熔断器打开的次数 | 熔断器处于打开的时间(次数 × 1 s) | 发出的调用 | 其中拿到 200 | 其中超时 | 服务端白干(客户端已超时仍处理完) --------+----------+----------------------+-------+----------+------+------------------ 100 ms | 16 | 16 s / 20 s | 974 | 768 | 206 | 206 1000 ms | 0 | 0 s / 20 s | 2210 | 2210 | 0 | 0 (连接类错误 0 次;不是超时,应为 0) 下游完全健康,但超时 100 ms 把 20% 的慢请求全算成失败,熔断器反复打开;被拒的请求本来都能成功(打开期间调用方什么也拿不到)。超时要比下游的正常尾延迟长
健康下游的慢请求被当作失败,熔断器反复打开,打开期间所有请求都拿不到结果。