再試行方法

このページでは、Cloud Storage へのリクエストが失敗した場合の指数バックオフなど、再試行方法について説明します。

概要

Cloud Storage へのリクエストに失敗した場合に再試行するかどうかを決定するには、リクエストのタイプとべき等性を検討します。これにより、オペレーションを安全に再試行できるかどうかが決まります。一般に、次の種類のリクエストは切り捨て型指数バックオフで再試行します。

  • データまたはメタデータのアップロードとダウンロードを含め、HTTP 5xx のレスポンス コードを返す Cloud Storage へのすべてのリクエスト。

  • HTTP 429 レスポンス コードを返す Cloud Storage へのリクエスト。ただし、再開可能なアップロードを使用してデータをアップロードするリクエストは除きます。

  • HTTP 408 レスポンス コードを返す、再開可能なアップロードXML API マルチパート アップロード

  • ソケット タイムアウトと TCP 切断。

詳細については、JSONXML のステータス コードとエラーコードをご覧ください。

指数バックオフ アルゴリズム

切り捨て型指数バックオフは、ネットワーク アプリケーションの標準的なエラー処理方法で、クライアントはリクエスト間の遅延を増加させながら、失敗したリクエストを定期的に再試行します。

指数バックオフのアルゴリズムは、再試行の待ち時間の間隔を最大バックオフ時間まで増加させながら、指数関数的にリクエストを再試行します。次に例を示します。

  1. Cloud Storage へのリクエストを作成します。

  2. リクエストが失敗した場合、1 + random_number_milliseconds 秒待ってから、リクエストを再試行します。

  3. リクエストが失敗した場合、2 + random_number_milliseconds 秒待ってから、リクエストを再試行します。

  4. リクエストが失敗した場合、4 + random_number_milliseconds 秒待ってから、リクエストを再試行します。

  5. このようにして、最大 maximum_backoff 時間まで繰り返します。

  6. 最大時間(deadline)まで待機と再試行を継続しますが、再試行間の maximum_backoff の待機期間は増えません。

ここで

  • 待ち時間は min((2n +random_number_milliseconds),maximum_backoff) で、n はイテレーション(リクエスト)のたびに +1 されます。

  • 上記のフローで、random_number_milliseconds は、1,000 ミリ秒以下の乱数です。これにより、多数のクライアントが同期され、再試行が一度に実行されて、リクエストが同時に次々と送信されるような状況を避けることができます。random_number_milliseconds の値は再試行リクエストの後に毎回再計算されます。

  • 通常、maximum_backoff は 32 秒または 64 秒です。適切な値はユースケースによって異なります。

maximum_backoff 時間に達した後も再試行を継続できますが、アプリケーションが応答不能にならないように、一定時間が経過した後にリクエストが失敗するように設定することをおすすめします。たとえば、クライアントで 64 秒の maximum_backoff 時間が使用されている場合、この値に達した後は、クライアントは 64 秒ごとに再試行を繰り返します。その後、600 秒の deadline の後にクライアントは再試行を停止します。

クライアントの再試行の待ち時間の間隔や再試行の回数は、ユースケースとネットワークの状態によって異なります。たとえば、アプリケーションのモバイル クライアントでは、同じアプリケーションのデスクトップ クライアントに比べて、より多くの再試行回数とより長い再試行間隔が必要になる可能性があります。

maximum_backoff と再試行に対して許容される追加時間を合計した時間を超えたために再試行リクエストが失敗した場合は、サポートとヘルプにリストされているいずれかの方法で、エラーのレポートまたはログを作成してください。

べき等性

失敗したリクエストを Cloud Storage に再試行しても安全かどうかを判断するには、リクエストがべき等かどうかを検討します。べき等であれば、同じオペレーションを複数回実行しても、対象リソースの状態は同じ結果になります。通常、べき等オペレーションは安全に再試行できます。

たとえば、次のような条件を満たしていれば、べき等性を実現できます。

  • オペレーションを連続してリクエストしても、対象リソースに対して結果が生成される。

  • オペレーションが 1 回だけ成功する。

  • 対象リソースの状態に対して観察可能な結果がない。

たとえば、バケットのリストを取得するリクエストは、リクエストが複数回成功した場合でも、同じ結果になります。一方、新しい Pub/Sub 通知の作成などのオペレーションはべき等ではありません。リクエストが成功するたびに新しい通知 ID が生成されるためです。

条件付きべき等性

リクエストのサブセットは条件付きべき等性になります。つまり、特定のオプション引数が含まれる場合にのみ、べき等になります。条件付きで安全に再試行できるオペレーションは、条件のケースに該当した場合にのみデフォルトで再試行されます。Cloud Storage は、リクエストの条件ケースとして前提条件と ETag を受け入れます。

Cloud Storage ツールごとの再試行方法

以下のタブをクリックすると、各 Cloud Storage ツールの再試行方法について推奨事項が表示されます。

Console

Cloud Console が Cloud Storage にリクエストを送信し、必要なバックオフを処理します。

gsutil

gsutil は、概要セクションに表示されたエラーを再試行します。その際、追加のアクションは必要ありません。次のようなエラーに対しては、対処が必要となる場合があります。

  • 認証情報が無効であるか、十分な権限がない。

  • プロキシ構成の問題でネットワークに接続できない。

  • -m top-level フラグを使用するコマンドで失敗した個々のオペレーション。

再試行可能なエラーの場合、次のような再送時間算出法に従ってリクエストを再試行します。デフォルトでは、gsutil は約 10 分間(1+2+4+8+16+32+60... 秒)で 23 回再試行します。

  • リクエストが失敗した場合、[0..1] 秒間待機して再試行します。
  • さらにリクエストが失敗した場合、[0..2] 秒待機して再試行します。
  • さらにリクエストが失敗した場合、[0..4] 秒間待機して再試行します。
  • このようにして、最大 23 回の再試行を繰り返します。1 回の再試行時間の上限はデフォルトで 60 秒です。

再試行の回数と 1 回の再試行時間の上限を設定するには、.boto 構成ファイル"[Boto]" セクションにある num_retriesmax_retry_delay 構成変数を編集します。

gsutil cprsync コマンドを使用するデータ転送の場合、転送を再開するという方法でも再試行機能が実行されます。

クライアント ライブラリ

C++

C++ クライアント ライブラリは、デフォルトで指数バックオフを使用します。

C#

C# クライアント ライブラリは、デフォルトで指数バックオフを使用します。

Go

Go クライアント ライブラリは、デフォルトで指数バックオフが使用されます。

Java

Java クライアント ライブラリは、デフォルトで指数バックオフを使用します。

Node.js

Node.js では、autoRetry パラメータを使用して、バックオフ方法に従ったリクエストの再試行を自動的に行うことができます。

PHP

PHP クライアント ライブラリは、デフォルトで指数バックオフを使用します。

Python

Python クライアント ライブラリでは、メディアとメディア以外のオペレーションで再試行方法が異なります。

  • メディア オペレーションには、ペイロード データを取得するアクションとオブジェクトに送信するアクションがすべて含まれます。たとえば、Client.download_blob_to_file など、upload または download で始まる Blob のすべてのメソッドが含まれます。

  • メディア以外のオペレーションは、オブジェクト メタデータのみを処理するアクションです。

メディアとメディア以外のオペレーションのデフォルトでは、以下のエラーコードに対する再試行がサポートされます。

  • 接続エラー:
    • requests.exceptions.ConnectionError
    • requests.exceptions.ChunkedEncodingError(メディア API 呼び出しのみ)
  • HTTP コード:
    • 429 Too Many Requests
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
    • 508 Resource Limit Exceeded

Python によるオペレーションでは、指数バックオフとして次のデフォルト設定が使用されます。

デフォルト設定 メディア呼び出し メディア以外の呼び出し
最初の待機時間(秒) 1 1
繰り返し間隔(秒) 2 2
最大待機時間(秒) 64 60
デフォルトの期限(秒) 600 120
ジッターの実装 ×

メディア オペレーションとメディア以外のオペレーションのサブセットは、特定のオプション引数が含まれる場合にのみ、べき等になります。条件付きで安全に再試行できるオペレーションは、条件のケースに一致した場合にのみ、デフォルトで再試行されます。現在、次のような条件があります。

  • DEFAULT_RETRY_IF_GENERATION_SPECIFIED

    • メソッドに if generation または if_generation_match が引数として渡された場合は、安全に再試行できます。多くの場合、メソッドはいずれかのパラメータを受け入れます。
  • DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED

    • メソッドに if_metageneration_match が引数として渡された場合は、安全に再試行できます。
  • DEFAULT_RETRY_IF_ETAG_IN_JSON

    • メソッドが etag を JSON リクエスト本文に挿入する場合は、安全に再試行できます。HMACKeyMetadata.update() の場合、HMACKeyMetadata オブジェクト自体で etag を設定する必要があります。他のクラスの set_iam_policy() メソッドの場合、メソッドに渡される policy 引数で etag を設定する必要があります。

メディア オペレーションの再試行ポリシー

メディア オペレーションの場合は、upload メソッドの num_retries 引数を構成して、アップロードの再試行回数を指定できます。デフォルトでは、べき等を保証するために、if_metageneration_match 条件を含むアップロードのみが再試行されます。num_retries 引数を設定すると、デフォルトの動作がオーバーライドされ、if_metageneration_match 条件がなくても再試行が保証されます。

メディア以外のオペレーションの再試行ポリシー

安全または条件付きで安全に再試行できるメディア以外のオペレーションには、メソッドのシグネチャに retry パラメータが追加されています。これらのパラメータのデフォルトは次のいずれかです。

  • DEFAULT_RETRY
  • DEFAULT_RETRY_IF_GENERATION_SPECIFIED
  • DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED
  • DEFAULT_RETRY_IF_ETAG_IN_JSON

デフォルトの再試行動作を変更するには、with_XXX メソッドを呼び出して google.cloud.storage.retry.DEFAULT_RETRY オブジェクトのコピーを作成します。たとえば、デフォルトの期限を 30 秒に変更するには、retry=DEFAULT_RETRY.with_deadline(30) を渡します。属性は 1 つずつ変更してください。詳細については、google-api-core Retry リファレンスをご覧ください。

独自の条件付き再試行を構成するには、ConditionalRetryPolicy オブジェクトを作成し、カスタム Retry オブジェクトを DEFAULT_RETRY_IF_GENERATION_SPECIFIEDDEFAULT_RETRY_IF_METAGENERATION_SPECIFIED、または DEFAULT_RETRY_IF_ETAG_IN_JSON のいずれかでラップします。

カスタマイズされた条件付き再試行の例を以下に示します。

  • blob.reload() は、デフォルトで DEFAULT_RETRY を使用します。関数がまったく再試行されないようにするには、blob.reload(retry=None) として呼び出します。

  • bucket.update() は、デフォルトで DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED を使用します。メタ世代番号が指定されていない場合でも関数が再試行するようにするには、次のように呼び出します。

    from google.cloud.storage.retry import DEFAULT_RETRY
    bucket.update(retry=DEFAULT_RETRY)
  • bucket.list_blobs() は、デフォルトで DEFAULT_RETRY を使用します。API 呼び出しがデフォルトの 120 秒ではなく、20 秒で再試行されるようにするには、次のように呼び出します。

    from google.cloud.storage.retry import DEFAULT_RETRY
    modified_retry = DEFAULT_RETRY.with_deadline(20)
    bucket.list_blobs(retry=modified_retry)

Ruby

Ruby クライアント ライブラリは、デフォルトで指数バックオフを使用します。

REST API

JSON または XML API を直接呼び出す場合は、指数バックオフ アルゴリズムを使用して独自の再試行方法を実装する必要があります。

オペレーションのべき等性

次の表に、べき等性の各カテゴリに属する Cloud Storage オペレーションの一覧を示します。

べき等性 オペレーション
常にべき等
  • すべての取得リクエストと一覧表示リクエスト
  • バケットを挿入または削除する
  • バケットの IAM ポリシーと権限のテスト
  • 保持ポリシーをロックする
  • HMAC キーまたは Pub/Sub 通知を削除する
条件付きべき等性
  • HTTP 前提条件として IfMetagenerationMatch または ETag を持つバケットの更新 / パッチ リクエスト
  • HTTP 前提条件として IfMetagenerationMatch または ETag を持つオブジェクトの更新 / パッチ リクエスト
  • HTTP 前提条件またはリソース本文で ETag を使用してバケットの IAM ポリシーを設定する
  • HTTP 前提条件またはリソースの本文で ETag を使用して HMAC キーを更新する
  • ifGenerationMatch を使用してオブジェクトを挿入、コピー、作成、書き換える
  • ifGenerationMatch(またはオブジェクト バージョンの世代番号)を持つオブジェクトを削除する
べき等でない
  • HMAC キーを作成する
  • Pub/Sub 通知を作成する
  • バケットとオブジェクトの ACL、またはデフォルト オブジェクト ACL のパッチ / 更新リクエストを作成、削除、または送信する

次のステップ