主动探测和实例上报心跳,哪个更早发现故障?进程没死但处理不了请求时,心跳还有意义吗?探测的参数和线程池大小怎么影响摘除延迟?这篇用本机的小服务量出来。
探测间隔 · 失败阈值 | crash:摘除延迟 最短 / 中位数 / 最长 | hang:摘除延迟 最短 / 中位数 / 最长 ------------------+--------------------------+------------------------ I = 0.5 s · K = 1 | 0.00 / 0.17 / 0.48 s | 0.40 / 0.59 / 0.80 s I = 0.5 s · K = 3 | 1.01 / 1.25 / 1.45 s | 1.33 / 1.54 / 1.75 s I = 1.0 s · K = 1 | 0.01 / 0.18 / 0.78 s | 0.32 / 0.84 / 1.30 s I = 1.0 s · K = 3 | 2.04 / 2.67 / 2.95 s | 2.48 / 2.81 / 3.26 s 摘除延迟大致在 (K−1)×I 到 K×I 加上探测超时之间:crash 时连接立刻被拒,每次探测立刻失败;hang 时每次探测要等满 0.3 s 的超时才算失败,所以多出一个超时
摘除延迟在 (K−1)×I 到 K×I 之间;hang 时每次探测要等满超时。
故障 | 心跳 + TTL 1.5 s:摘除延迟(中位数) | 探测 I = 0.5 s · K = 3:摘除延迟(中位数) | 故障之后发给它的 /work 请求成功数 ------+--------------------------+--------------------------------+--------------------- crash | 1.32 s(5 / 5 次摘除) | 1.33 s(5 / 5 次摘除) | 0 / 50 hang | 一直认为健康(0 / 5 次摘除) | 2.24 s(5 / 5 次摘除) | 0 / 50 hang 时心跳线程和业务线程是独立的,心跳继续上报“我还活着”,注册中心不会摘掉它,发给它的请求全部超时;探测方因为 /health 也走业务线程池,探测会失败,所以能摘掉。心跳只能证明“进程活着、心跳线程活着”,不能证明“能处理请求”;要让心跳有意义,上报之前应当做一次真实的自检(走和业务一样的路径)
心跳只能证明进程和心跳线程还活着;业务线程卡死时心跳照常发,注册中心不会摘除。
线程池大小 | 一轮探测 200 个实例用时(中位数) | 3 轮范围 ------+---------------------+-------------- 10 | 2.07 s | 2.06 ~ 2.07 s 50 | 1.08 s | 1.06 ~ 1.08 s 200 | 1.07 s | 1.07 ~ 1.08 s 理论下界:20 个 hang 的实例各占一个线程 1 s,用 10 个线程就至少要 2 s 才能处理完它们;线程池太小时,少量 hang 的实例就会把整轮探测拖慢,其它健康实例的探测间隔也跟着变长——探测间隔设成 1 s,实际可能是几秒
探测线程池太小时,少量 hang 的实例就拖慢整轮探测。