【Cloud Tasks】リトライ回数と再試行の期間を設定する方法

【Cloud Tasks】リトライ回数と再試行の期間を設定する方法 GCP

Cloud Tasks のキューに、失敗したタスクを何回・どれだけの期間まで再試行するかを設定する方法をまとめます。gcloud tasks queues update で既存のキューを変える手順と、Terraform の google_cloud_tasks_queue で書く場合の両方を扱います。前提は Cloud Tasks API v2 と、Cloud Run などの HTTP ターゲットにタスクを送るキューです。回数と期間の止まり方には、設定した数字どおりに止まらない落とし穴があるので、その確かめ方も載せます。

リトライの決まりを先に押さえる

何が「失敗」になるか

HTTP ターゲットのタスクは、送り先が 200〜299 を返すと成功になり、キューから消えます。それ以外のステータスコードが返ったとき、または応答が来なかったときは失敗として扱われ、キューのリトライ設定に従って再試行されます。

応答を待つ時間はタスクの dispatchDeadline で決まります。HTTP ターゲットの既定は10分で、15秒から30分の間で指定できます。期限を過ぎると、その試行は DEADLINE_EXCEEDED の失敗になります。Cloud Tasks が待つのをやめても、送り先の処理が止まるとは限らない点に注意してください。

設定する5つの値

gcloud のフラグ Terraform の retry_config 意味
--max-attempts max_attempts 1回目を含めた試行の最大回数。-1 で無制限
--max-retry-duration max_retry_duration 最初の試行から数えて、再試行を続ける期間。0s で無制限
--min-backoff min_backoff 再試行までに待つ最短の時間
--max-backoff max_backoff 再試行までに待つ最長の時間
--max-doublings max_doublings 待ち時間を2倍にしていく回数

時間の値は 5s のように s で終わる文字列で書きます。

回数と期間の両方を満たすまで止まらない

max_attempts と max_retry_duration は、どちらか片方に達したら止まるのではありません。試行回数が max_attempts に達し、かつ最初の試行から max_retry_duration が過ぎたときに再試行が終わり、タスクは削除されます。

両方を無制限(-1 と 0s)にすると、タスクの最大保持期間(31日)に達するまで再試行が続きます。

待ち時間の伸び方

待ち時間は min_backoff から始まり、max_doublings 回だけ2倍になり、その後は一定の幅で伸びて、最後は max_backoff の間隔で再試行します。

公式ドキュメントの例では、min_backoff が 10s、max_backoff が 300s、max_doublings が 3 のとき、待ち時間は次のようになります。

10s, 20s, 40s, 80s, 160s, 240s, 300s, 300s, ...

3回2倍になった後は 2^3 × 10s = 80s ずつ伸び、300s で頭打ちになります。

gcloud で既存のキューを設定する

1. 今の設定を確かめる

gcloud tasks queues describe QUEUE_ID --location=LOCATION

QUEUE_ID はキューの名前、LOCATION はキューのリージョン(asia-northeast1 など)です。パラメータを指定せずに作ったキューでは、retryConfig は次のように出ます。

retryConfig:
  maxAttempts: 100
  maxBackoff: 3600s
  maxDoublings: 16
  minBackoff: 0.100s
state: RUNNING

--location を省くと、プロジェクトに紐づく App Engine アプリのリージョンが使われます。App Engine を使っていないプロジェクトでは毎回付けてください。

2. リトライの値を変える

例として、ユーザーの操作に応じて数十秒以内に結果を返したい処理を、3回まで・40秒以内で再試行するキューにします。

gcloud tasks queues update QUEUE_ID \
  --location=LOCATION \
  --max-attempts=3 \
  --max-retry-duration=40s \
  --min-backoff=1s \
  --max-backoff=10s \
  --max-doublings=3

フラグは変えたいものだけ付ければよく、付けなかった値はそのまま残ります。キューを新しく作るときは、同じフラグを gcloud tasks queues create に付けます。

3. 設定を既定に戻す

値を指定し直すのではなく既定に戻したいときは、--clear- の付いたフラグを使います。

gcloud tasks queues update QUEUE_ID \
  --location=LOCATION \
  --clear-max-attempts \
  --clear-max-retry-duration

Terraform で設定する

google_cloud_tasks_queue の retry_config ブロックに書きます。

resource "google_cloud_tasks_queue" "requests" {
  name     = "summary-requests"
  location = "asia-northeast1"

  retry_config {
    max_attempts       = 3
    max_retry_duration = "40s"
    min_backoff        = "1s"
    max_backoff        = "10s"
    max_doublings      = 3
  }
}

retry_config を書かずに作ったキューでは、Cloud Tasks が既定の値を選びます。gcloud とコンソールで変えた値は、次の terraform apply で Terraform の値に戻されるので、Terraform で管理しているキューは Terraform 側だけで変えます。

動作を確認する

設定が入ったかは describe で確かめます。

gcloud tasks queues describe QUEUE_ID --location=LOCATION \
  --format='yaml(retryConfig)'

期待する出力は次のとおりです。

retryConfig:
  maxAttempts: 3
  maxBackoff: 10s
  maxDoublings: 3
  maxRetryDuration: 40s
  minBackoff: 1s

実際に何回送られたかを見るには、キューのログを Cloud Logging に出します。--log-sampling-ratio は書き出す操作の割合で、既定の 0.0 では何も出ません。

gcloud tasks queues update QUEUE_ID \
  --location=LOCATION \
  --log-sampling-ratio=1.0

わざと 500 を返すエンドポイントにタスクを1件送り、試行ごとのログが出る間隔と回数が設定どおりかを見ます。確かめ終わったら、ログの量を抑えるために割合を下げておきます。

うまくいかないとき

max_attempts を3にしたのに、3回より多く送られる

回数と期間の両方を満たすまで再試行は終わりません。max_attempts が 3 でも、3回目の失敗の時点で max_retry_duration が過ぎていなければ、期間が過ぎるまで再試行が続きます。

回数だけで止めたいなら、max_retry_duration を短くするか、待ち時間(min_backoff と max_backoff)を伸ばして、3回目より前に期間が過ぎるようにします。

設定より再試行の間隔が長い

送り先が 429(Too Many Requests)や 503(Service Unavailable)を返したとき、またはエラーの割合が高いとき、Cloud Tasks はキューの設定より長い待ち時間を使って送る速さを落とします。応答に Retry-After ヘッダーがあれば、それも考慮されます。リトライ設定を変える前に、送り先がどのステータスコードを返しているかをログで確かめてください。

送り先は処理を終えているのに再試行される

送り先が dispatchDeadline までに応答を返していない可能性があります。HTTP ターゲットの既定は10分です。処理に時間がかかる場合は、タスクを作るときに dispatchDeadline を処理時間より長くするか、受け取ったらすぐ 2xx を返して処理を別に回す形にします。再試行で同じ処理が2回走っても困らないよう、送り先の処理は同じタスクを何度受けても結果が変わらない作りにしておきます。

タスクごとに違うリトライ設定にしたい

リトライ設定はキュー単位のほか、タスク単位でも指定できます。タスクに指定した値は、そのタスクについてキューの値より優先されます。

参考

この記事を書いた人

渋谷で働くよわよわエンジニア。TypeScript(Next.js/Node.js)/Golang/AWS/Flutterなど
LINE API Expert(2023/1~)

tokkuをフォローする
オススメ記事
在宅ワークが多くなって、デスクの配線周りに困っている方は、拡張デスクの導入がおすすめです。Windows/MacOS/Linuxの複数の機器をスッキリとデスク周りに収める事ができました!リモートからサーバーメンテを行うインフラエンジニアは必見です!
GCP
シェアする
tokkuをフォローする

コメント

タイトルとURLをコピーしました