backoff付きリトライとは?解説
backoff付きリトライは、即座にリトライするのではなく試行の間に次第に長くなる間隔を待ち、苦しんでいるシステムに回復する時間を与えます。
即座のリトライは効率的に見えますが、多くのクライアントが過負荷のサービスに対して一斉にリトライすると、サービスが最も対処できないまさにそのときに、さらに負荷を積み重ねてしまいます。backoffは試行を時間的に分散させ、システムに回復の余地を与えます。
即座のリトライの問題
上流が過負荷で失敗している場合、即座にリトライすると過負荷が悪化します。高速なリトライごとに負荷が加わり、サービスは飽和したままになり、自己強化的な失敗に陥ります。backoffは、意図的で増加していく休止を導入することでそのループを断ち切ります。
固定backoff vs 指数backoff
固定backoffは毎回同じ間隔(たとえば5秒)を待ちます。指数backoffは試行ごとに待ち時間を倍にし(1s、2s、4s、8s)、失敗が続くと積極的に後退します。指数が通常の選択です。適応的だからです。短い瞬断には短い待ち、本当に停止しているときには長い待ちになります。
なぜjitterが重要なのか
すべてのクライアントが同じbackoffスケジュールを使うと、全員が同じ瞬間にリトライし、thundering-herd問題を1拍遅れで再現してしまいます。jitterは各遅延にランダム性を加え、リトライが同期する代わりに分散するようにします。jitter付きのbackoffが標準的で堅牢なパターンです。
CIにおけるbackoff
CIでは、backoffはネットワークとregistryの処理で最も重要になります。パッケージのインストール、イメージのpull、レート制限されたサービスへのAPI呼び出しなどです。待って増加していくリトライは、1秒間に3回発火するものよりも、一時的に過負荷なregistryに対してはるかに成功しやすくなります。
Latchkeyの視点
Latchkeyの自己修復managed runnerがregistryのタイムアウトのような一時的な問題で失敗したjobをリトライするとき、即座にではなく賢明にリトライします。そのため回復がすでに苦しんでいる上流に負荷を加えることはなく、一度きりの瞬断でbuildが失敗することもありません。
重要なポイント
- backoffはリトライ試行の間に増加する間隔を待ちます。
- 高速なリトライが過負荷のシステムを悪化させるのを防ぎます。
- 指数backoffは適応的で、jitterは同期したリトライを防ぎます。
- CIでは、ネットワークとregistryの処理で最も重要になります。