♣️
Go言語でエクスポネンシャルバックオフ処理を実装する パート2
前回の記事ではエクスポネンシャルバックオフを自前で実装しましたが、今回はcenkalti/backoffというライブラリを使って実装してみたいと思います。
実際のコード
// メインの処理
func doOperation() error{
fmt.Printf("doOperation ")
// わざとエラーで返す
return errors.New("error")
}
func doNotify(err error, duration time.Duration) {
fmt.Printf("エラー: %v %d秒後に再試行します...\n", err, duration/time.Second)
}
func main() {
operation := backoff.Operation(doOperation)
notify := backoff.Notify(doNotify)
exponentialBackOff := backoff.NewExponentialBackOff()
// リトライの初期間隔
exponentialBackOff.InitialInterval = 1 * time.Second
// リトライ間隔を決めるランダム値
exponentialBackOff.RandomizationFactor = 0
// リトライ間隔を決める乗数
exponentialBackOff.Multiplier = 2
err :=backoff.RetryNotify(operation,backoff.WithMaxRetries(exponentialBackOff,3),notify)
if err != nil {
fmt.Println("処理失敗")
} else {
fmt.Println("処理成功")
}
}
実行結果
doOperation
エラー: error 1秒後に再試行します...
doOperation
エラー: error 2秒後に再試行します...
doOperation
エラー: error 4秒後に再試行します...
doOperation
処理失敗
コードの説明
リトライ間隔は RetryInterval * (範囲 [1 - RandomizationFactor, 1 + RandomizationFactor] 内のランダム値)
の式を元に算出されており、今回の場合だと
InitialInterval(RetryInterval) = 1秒
RandomizationFactor = 0
Multiplier = 2
と指定しており、1秒、2秒、4秒、8秒…ごとの間隔でリトライを実行します。
backoff.RetryNotify(operation,backoff.WithMaxRetries(exponentialBackOff,3),notify)
では WithMaxRetries
の第2引数でリトライ回数を指定しています。
今回は3回リトライを実行するように指定しています。
エラーによってリトライするかどうか判定する
エラーによってはリトライさせずに処理を終了させたい場合があると思います。
backoff.Permanent()
を使うことで任意のエラーの時はリトライせずに終了させることができます。
func doOperation() error {
// 0〜1の乱数を生成
randInt := rand.Intn(2)
if randInt == 0 {
return errors.New("error need retry")
}
// randIntが0以外の時はリトライせずに処理を終了する
return backoff.Permanent(errors.New("error permanent"))
}
func doNotify(err error, duration time.Duration) {
fmt.Printf("エラー: %v %d秒後に再試行します...\n", err, duration/time.Second)
}
func main() {
operation := backoff.Operation(doOperation)
notify := backoff.Notify(doNotify)
exponentialBackOff := backoff.NewExponentialBackOff()
exponentialBackOff.InitialInterval = 1 * time.Second
exponentialBackOff.RandomizationFactor = 0
exponentialBackOff.Multiplier = 2
err := backoff.RetryNotify(operation,backoff.WithMaxRetries(exponentialBackOff, 3), notify)
if err != nil {
fmt.Printf("処理失敗 %v \n", err)
} else {
fmt.Println("処理成功")
}
}
実行結果
エラー: error need retry 1秒後に再試行します...
エラー: error need retry 2秒後に再試行します...
処理失敗 error permanent
まとめ
cenkalti/backoffというライブラリを使ってエクスポネンシャルバックオフを実装してみました。
簡単に実装できるので、手軽にリトライ処理を実装したいと思った場合はこのライブラリを使ってみるといいかもしれません。
Discussion