0Pricing
Go Academy · レッスン

バックオフとリトライ

バックオフして再試行します

「バックオフとリトライ」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

リトライする理由

一時的な障害、タイムアウト、接続切断、一時的な503などは、2回目の試行で成功することがよくあります。リトライによって、不安定な処理を呼び出し元に負担をかけず、信頼性の高い処理にできます。

単純なリトライは危険

タイトなループで直ちにリトライすると、問題を抱えたサービスに大量のリクエストを送り続け、リトライストームを引き起こす可能性があります。試行の間には遅延が必要で、その遅延は徐々に長くするべきです。

指数バックオフ

指数バックオフでは、失敗するたびに待機時間を2倍にします。100ms、200ms、400ms、800msのように増加します。これにより、下流のサービスが復旧するための時間を確保できます。

delay := 100 * time.Millisecond
for attempt := 0; attempt < 5; attempt++ {
    // try, on failure:
    time.Sleep(delay)
    delay *= 2
}

ジッターの追加

多くのクライアントが同じタイミングでバックオフすると、全クライアントが同時にリトライする、いわゆるthundering herdが発生します。ジッターによって各遅延を少しずつランダム化し、リトライのタイミングを分散させます。

jitter := time.Duration(rand.Int63n(int64(delay) / 2))
time.Sleep(delay + jitter)

遅延の上限設定

指数的な増加によって、待機時間はすぐに非常に長くなります。試行の間に何分も待たずに済むよう、遅延に最大値を設定します。

if delay > 2*time.Second {
    delay = 2 * time.Second
}

試行回数の制限

試行回数には必ず上限を設けます。上限に達したら最後のエラーを返し、無限にリトライするのではなく、呼び出し元が次の対応を判断できるようにします。

冪等な処理だけをリトライする

リトライが安全なのは、同じ操作を2回実行しても問題が起きない場合だけです。GETは冪等ですが、カードに課金する冪等でないPOSTを無条件にリトライしてはいけません。必要に応じて冪等性キーを使用します。

完全なバックオフリトライ

このプログラムは、2回失敗した後に成功する関数をリトライし、そのたびに遅延時間を2倍にします。標準ライブラリだけを使用しています。

package main

import (
    "errors"
    "fmt"
    "time"
)

func flaky(attempt int) error {
    if attempt < 2 {
        return errors.New("temporary failure")
    }
    return nil
}

func main() {
    delay := 50 * time.Millisecond
    var err error
    for attempt := 0; attempt < 5; attempt++ {
        err = flaky(attempt)
        if err == nil {
            fmt.Println("succeeded on attempt", attempt)
            return
        }
        fmt.Printf("attempt %d failed, waiting %v\n", attempt, delay)
        time.Sleep(delay)
        delay *= 2
    }
    fmt.Println("gave up:", err)
}

contextへの対応

contextをリトライループに渡し、スリープ中にctx.Done()をselectします。これにより、キャンセルまたはタイムアウトした呼び出し元は、直ちにリトライを停止できます。

select {
case <-ctx.Done():
    return ctx.Err()
case <-time.After(delay):
}

エラーの判別

すべてのエラーがリトライ可能とは限りません。400 Bad Requestは何度試しても失敗します。エラーまたはステータスコードを調べ、タイムアウト、429、5xxなど一時的な障害の場合にだけリトライします。

サーキットブレーカー

障害が続く場合、サーキットブレーカーは各呼び出しをリトライする代わりに、クールダウン期間中のリクエスト送信を停止します。明らかに停止している依存先を保護することで、バックオフを補完します。

クイックチェック

バックオフに関する知識を確認しましょう。

振り返り

バックオフとリトライについて学びました。

  • 指数バックオフは、失敗するたびに遅延を2倍にする
  • ジッターによって同期したリトライストームを防ぐ
  • 遅延に上限を設け、試行回数を制限する
  • 冪等な処理、またはリトライ可能なエラーの場合だけリトライする
  • キャンセルに対応するためcontextを尊重する

よくある質問

「バックオフとリトライ」レッスンは無料ですか?

はい。「バックオフとリトライ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「バックオフとリトライ」で何を学びますか?

バックオフして再試行します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「バックオフとリトライ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. トークンバケットの概念
  2. golang.org/x/time/rate
  3. Goroutineのスロットリング
  4. バックオフとリトライ
← Go Academyに戻る