Curator 的重试策略只有一行配置,但它决定了服务端抖一下时你的调用是失败还是成功。这篇用真实的不可用服务端和真实的重启,量 6 种策略放弃前花多久、策略对象在内部被怎么调用,以及哪种策略能撑过一次重启。
RetryOneTime(500) → ConnectionLossException,共 2.3 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[500 ms, 放弃], main=[500 ms, 放弃]}
RetryNTimes(3, 200) → ConnectionLossException,共 4.6 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[200 ms, 200 ms, 200 ms, 放弃], main=[200 ms, 200 ms, 200 ms, 放弃]}
ExponentialBackoffRetry(100, 5) → ConnectionLossException,共 6.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 100 ms, 500 ms, 800 ms, 600 ms, 放弃], main=[100 ms, 100 ms, 500 ms, 400 ms, 900 ms, 放弃]}
ExponentialBackoffRetry(100, 5, maxSleep=300) → ConnectionLossException,共 6.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 200 ms, 300 ms, 300 ms, 300 ms, 放弃], main=[100 ms, 300 ms, 300 ms, 300 ms, 300 ms, 放弃]}
BoundedExponentialBackoffRetry(100, 800, 6) → ConnectionLossException,共 7.9 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 100 ms, 400 ms, 500 ms, 800 ms, 800 ms, 放弃], main=[100 ms, 100 ms, 200 ms, 100 ms, 800 ms, 800 ms, 放弃]}
RetryUntilElapsed(2000, 300) → ConnectionLossException,共 3.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[300 ms, 300 ms, 300 ms, 300 ms, 300 ms, 放弃], main=[300 ms, 300 ms, 300 ms, 放弃]}连接超时设为 500 ms,所以每次尝试连接本身就要 0.5 s;总耗时是「重试间隔 + 每次尝试连接的等待」的和,不是只看重试间隔。
RetryOneTime(500) → ConnectionLossException,共 2.3 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[500 ms, 放弃], main=[500 ms, 放弃]}
RetryNTimes(3, 200) → ConnectionLossException,共 4.6 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[200 ms, 200 ms, 200 ms, 放弃], main=[200 ms, 200 ms, 200 ms, 放弃]}
ExponentialBackoffRetry(100, 5) → ConnectionLossException,共 6.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 100 ms, 500 ms, 800 ms, 600 ms, 放弃], main=[100 ms, 100 ms, 500 ms, 400 ms, 900 ms, 放弃]}
ExponentialBackoffRetry(100, 5, maxSleep=300) → ConnectionLossException,共 6.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 200 ms, 300 ms, 300 ms, 300 ms, 放弃], main=[100 ms, 300 ms, 300 ms, 300 ms, 300 ms, 放弃]}
BoundedExponentialBackoffRetry(100, 800, 6) → ConnectionLossException,共 7.9 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[100 ms, 100 ms, 400 ms, 500 ms, 800 ms, 800 ms, 放弃], main=[100 ms, 100 ms, 200 ms, 100 ms, 800 ms, 800 ms, 放弃]}
RetryUntilElapsed(2000, 300) → ConnectionLossException,共 3.8 s;各线程里 allowRetry 的睡眠序列 {Curator-Framework=[300 ms, 300 ms, 300 ms, 300 ms, 300 ms, 放弃], main=[300 ms, 300 ms, 300 ms, 放弃]}我没有去读 Curator 源码查这两条线程具体对应什么;只确认了日志里这两条线程各自从第 0 次开始计数。所以不要只按「策略里写的次数 × 间隔」去估算一次失败调用的总耗时,要在自己的环境里测。
RetryNTimes(1, 100) → ConnectionLossException,发起后 1.3 s 返回 RetryNTimes(5, 200) → 成功,发起后 3.5 s 返回 ExponentialBackoffRetry(100, 5) → 成功,发起后 2.8 s 返回 RetryUntilElapsed(10000, 200) → 成功,发起后 3.3 s 返回
服务端重启期间的客户端行为,也可以对照kazoo的「调用一直等到恢复」。Curator 里则是由策略决定等多久。