「エクスポネンシャルバックオーーーーーーーフッ!!!」
技名ではなくリトライ時に使うアルゴリズムの話です。
Exponential Backoff And Jitter とは
Exponential Backoff
分散システムとかでネットワーク通信に失敗した時、成功するまでやり直す(リトライ)事ってあるよね。
でも通信に失敗した時ってネットワークや通信先サーバーの高負荷が原因だったりするから、
短時間に何度もリトライするとさらに負荷を増やしちゃうかもしれないんだ。
そんなときはExponential Backoff!
初回リトライまでの間隔は1秒、次は2秒、その次は4秒..8秒....みたいにリトライ間隔を指数関数的(Exponential)に後退(Backoff)させることでネットワークや接続先サーバーの過負荷を軽減さえられるんだ。
Jitter
Exponential Backoffだけだとちょっと不安、例えば同時に100クライアントからアクセスされている場合、
1秒、2秒、4秒、8秒....のタイミングでドカッと100アクセスされてしまう可能性がある。
そんなときはJitter!
クライアントAはリトライ間隔を0.92秒、1.97秒、4.01秒、8.09秒...
クライアントBはリトライ間隔を1.06秒、2.03秒、3.97秒、7.92秒...
みたいに多少の揺らぎ(Jitter)を導入することでリクエスト集中の問題を解決できるよ。
GO言語でExponential Backoff And Jitterをやってみる
本題に入る。
今回は簡単にExponential Backoff And Jitterができる「retry」パッケージを使うよ。
まずはコード
// リトライしたい処理を定義
op := func() (string, error) {
fmt.Printf("some form of processing...(%v)\n", time.Now())
return "", errors.New("Error!!")
}
// リトライしたい処理をRetry関数に渡す
result, err := retry.RetryOneResult(op)
↓出力↓
some form of processing...(2023-05-04 22:41:23.8943312 +0900 JST m=+0.003652001)
some form of processing...(2023-05-04 22:41:24.1863735 +0900 JST m=+0.295694301)
some form of processing...(2023-05-04 22:41:24.684814 +0900 JST m=+0.794134801)
some form of processing...(2023-05-04 22:41:25.5369253 +0900 JST m=+1.646246101)
some form of processing...(2023-05-04 22:41:27.5995704 +0900 JST m=+3.708891201)
Fail: Maximum number of retries reached
こんな感じで簡単にリトライができるよ。
Go Playgroundでも書いてみた。
デフォルトは最大5回のリトライで初回リトライまでが100ミリ秒、最大の遅延は10秒になるよ。
このあたりは引数で調整可能。
初回リトライを2秒、最大3回にしてみる
以下のように引数を増やしてあげると簡単に調整ができるよ。
// リトライしたい処理を定義
op := func() (string, error) {
fmt.Printf("some form of processing...(%v)\n", time.Now())
return "", errors.New("Error!!")
}
// リトライしたい処理をRetry関数に渡す(初回リトライを2秒、最大3回)
result, err := retry.RetryOneResult(op, retry.WithInitialDelay(2*time.Second), retry.WithMaxRetries(3))
if err != nil {
fmt.Println("Fail:", err)
} else {
fmt.Println("Succeed:", result)
}
↓出力↓
some form of processing...(2023-05-04 22:50:57.5021196 +0900 JST m=+0.003110101)
some form of processing...(2023-05-04 22:51:01.5844456 +0900 JST m=+4.085436101)
some form of processing...(2023-05-04 22:51:10.9645184 +0900 JST m=+13.465508901)
Fail: Maximum number of retries reached
Go Playgroundでも書いてみた。
おしまい
みんなもネットワークやサーバーに優しいリトライをしよう!!