このページでは、失敗したリクエストを Cloud Storage ツールが再試行する方法と、再試行の動作をカスタマイズする方法について説明します。また、リクエストを再試行する際の考慮事項についても説明します。
概要
リクエストの再試行が安全かどうかは、次の 2 つの要素で決まります。
リクエストからの受信レスポンス。
リクエストのべき等性。
レスポンス
リクエストから返されたレスポンスは、リクエストの再試行に役立つかどうかを示します。通常、一時的な問題に関連するレスポンスは再試行できます。一方、永続的なエラーに関連するレスポンスは、リクエストを再試行する前に、承認や構成の変更などを行う必要があることを示します。次のレスポンスは、再試行する価値がある一時的な問題を示しています。
408
、429
、5xx
の HTTP レスポンス コード。- ソケット タイムアウトと TCP 切断。
詳細については、JSON と XML のステータス コードとエラーコードをご覧ください。
べき等性
べき等なリクエストは、対象リソースの最終状態を変更せずに繰り返し実行できるため、毎回同じ最終状態になります。たとえば、リスト オペレーションは、リソースを変更しないため、常にべき等です。一方、新しい Pub/Sub 通知の作成はべき等ではありません。リクエストが成功するたびに新しい通知 ID が生成されるためです。
以下に、オペレーションをべき等にする条件の例を示します。
オペレーションを連続してリクエストしても、対象リソースに対して結果が生成される。
オペレーションが 1 回だけ成功する。
対象リソースの状態に対して観察可能な結果がない。
再試行可能なレスポンスを受け取った場合は、リクエストのべき等性を考慮する必要があります。これは、べき等でないリクエストを再試行すると、競合状態などの競合が発生する可能性があるためです。
条件付きべき等性
リクエストのサブセットは条件付きべき等性になります。つまり、特定のオプション引数が含まれる場合にのみ、べき等になります。条件付きで安全に再試行できるオペレーションは、条件のケースに該当した場合にのみデフォルトで再試行されます。Cloud Storage は、リクエストの条件ケースとして前提条件と ETag を受け入れます。
オペレーションのべき等性
次の表に、べき等性の各カテゴリに属する Cloud Storage オペレーションの一覧を示します。
べき等性 | オペレーション |
---|---|
常にべき等 |
|
条件付きべき等性 |
|
べき等でない |
|
1 このフィールドは JSON API で使用できます。クライアント ライブラリで使用できるフィールドについては、関連するクライアント ライブラリのドキュメントをご覧ください。
Cloud Storage ツールの再試行方法の実装方法
コンソール
Trusted Cloud コンソールが Cloud Storage にリクエストを送信し、必要なバックオフを処理します。
コマンドライン
gcloud storage
コマンドは、レスポンス セクションに示されているエラーを再試行します。追加のアクションを行う必要はありません。次のようなエラーに対しては、対応が必要になる場合があります。
認証情報が無効であるか、十分な権限がない。
プロキシ構成の問題でネットワークに接続できない。
再試行可能なエラーの場合、gcloud CLI は切り捨てバイナリ指数バックオフを使用してリクエストを再試行します。gcloud CLI の場合、デフォルトの再試行の最大数は 32 です。
クライアント ライブラリ
C++
デフォルトでは、次の HTTP エラーコードに対する再試行と、接続が切断または正常に確立されなかったことを示すソケットエラーに対する再試行がサポートされます。
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
C++ ライブラリの指数バックオフと再試行のすべての設定を構成できます。ライブラリで実装されているアルゴリズムが要件に合わない場合は、カスタムコードを作成して独自の戦略を実装できます。
設定 | デフォルト値 |
---|---|
自動再試行 | True |
リクエストの再試行の最大時間 | 15 分 |
初期待機(バックオフ)時間 | 1 秒 |
反復処理ごとの待機時間乗数 | 2 |
最大待機時間 | 5 分 |
デフォルトでは、C++ ライブラリは再試行可能なエラーですべてのオペレーションを再試行します。また、べき等にすることなく、繰り返し成功したときに複数のリソースを削除または作成できます。べき等オペレーションのみを再試行するには、google::cloud::storage::StrictIdempotencyPolicy
クラスを使用します。
C#
C# クライアント ライブラリは、デフォルトで指数バックオフを使用します。
Go
デフォルトでは、オペレーションは次のエラーの再試行をサポートします。
- 接続エラー:
io.ErrUnexpectedEOF
: これは、一時的なネットワークの問題が原因で発生する可能性があります。connection refused
を含むurl.Error
: これは、一時的なネットワークの問題が原因で発生する可能性があります。connection reset by peer
を含むurl.Error
: Trusted Cloud by S3NS が接続をリセットしたことを意味します。net.ErrClosed
: Trusted Cloud by S3NS が接続を閉じたことを意味します。
- HTTP コード:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Temporary()
インターフェースを実装し、値をerr.Temporary() == true
に設定する際のエラー- Go 1.13 エラー ラッピングを使用してラップされた上記のエラーのいずれか
Go ライブラリでは、すべての指数バックオフ設定が構成可能です。デフォルトでは、Go によるオペレーションでは指数バックオフ用に次の設定が使用されます(デフォルトは gax から取得されます)。
設定 | デフォルト値(秒) |
---|---|
自動再試行 | べき等の場合は true |
最大試行回数 | 上限なし |
最初の再試行までの経過時間 | 1 秒 |
再試行遅延乗数 | 2.0 |
再試行の最大遅延 | 30 秒 |
合計タイムアウト(再開可能なチャンク アップロード) | 32 秒 |
合計タイムアウト(他のすべてのオペレーション) | 上限なし |
一般に、制御コンテキストがキャンセルされるか、クライアントが終了するか、一時的でないエラーが受信されない限り、再試行は無期限に続行されます。再試行の続行を停止するには、コンテキストのタイムアウトまたはキャンセルを使用します。この動作の唯一の例外は、書き込みを使用して再開可能なアップロードを実行する場合です。この場合、データ量が十分にあり、複数のリクエストが必要になります。このシナリオでは、各チャンクがタイムアウトし、デフォルトで 32 秒後に再試行を停止します。デフォルトのタイムアウトは Writer.ChunkRetryDeadline
を変更することで調整できます。
条件付きべき等(条件付きで安全に再試行できる)の Go オペレーションのサブセットがあります。これらのオペレーションは、次の特定の条件を満たす場合にのみ再試行されます。
GenerationMatch
またはGeneration
- 前提条件
GenerationMatch
が呼び出しに適用されていた場合、またはObjectHandle.Generation
が設定されていた場合は、再試行しても安全です。
- 前提条件
MetagenerationMatch
- 前提条件
MetagenerationMatch
が呼び出しに適用されていた場合は、再試行しても安全です。
- 前提条件
Etag
- メソッドが
etag
を JSON リクエスト本文に挿入する場合は、安全に再試行できます。HmacKeyMetadata.Etag
が設定されている場合にのみ、HMACKeyHandle.Update
で使用されます。
- メソッドが
RetryPolicy
はデフォルトで RetryPolicy.RetryIdempotent
に設定されています。デフォルトの再試行動作を変更する方法の例については、再試行のカスタマイズをご覧ください。
Java
デフォルトでは、オペレーションは次のエラーの再試行をサポートします。
- 接続エラー:
Connection reset by peer
: Trusted Cloud by S3NS が接続をリセットしたことを意味します。Unexpected connection closure
: Trusted Cloud by S3NS が接続を閉じたことを意味します。
- HTTP コード:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Java ライブラリでは、すべての指数バックオフ設定が構成可能です。デフォルトでは、Java によるオペレーションでは指数バックオフ用に次の設定が使用されます。
設定 | デフォルト値(秒) |
---|---|
自動再試行 | べき等の場合は true |
最大試行回数 | 6 |
最初の再試行までの経過時間 | 1 秒 |
再試行遅延乗数 | 2.0 |
再試行の最大遅延 | 32 秒 |
合計タイムアウト | 50 秒 |
初期 RPC タイムアウト | 50 秒 |
RPC タイムアウト乗数 | 1.0 |
最大 RPC タイムアウト | 50 秒 |
接続タイムアウト | 20 秒 |
読み取りタイムアウト | 20 秒 |
設定の詳細については、Java リファレンス ドキュメントの RetrySettings.Builder
と HttpTransportOptions.Builder
をご覧ください。
条件付きべき等(条件付きで安全に再試行できる)の Java オペレーションのサブセットがあります。これらのオペレーションは、特定の引数が含まれている場合にのみ再試行されます。
ifGenerationMatch
またはgeneration
- メソッドに
ifGenerationMatch
またはgeneration
がオプションとして渡された場合は、安全に再試行できます。
- メソッドに
ifMetagenerationMatch
ifMetagenerationMatch
がオプションとして渡された場合は、安全に再試行できます。
StorageOptions.setStorageRetryStrategy
はデフォルトで StorageRetryStrategy#getDefaultStorageRetryStrategy
に設定されています。
デフォルトの再試行動作を変更する方法の例については、再試行のカスタマイズをご覧ください。
Node.js
オペレーションでは、デフォルトで次のエラーコードの再試行がサポートされています。
- 接続エラー:
EAI_again
: これは DNS ルックアップ エラーです。詳細については、getaddrinfo
のドキュメントをご覧ください。Connection reset by peer
: Trusted Cloud by S3NS が接続をリセットしたことを意味します。Unexpected connection closure
: Trusted Cloud by S3NS が接続を閉じたことを意味します。
- HTTP コード:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Node.js ライブラリでは、すべての指数バックオフ設定が構成可能です。デフォルトで、Node.js を使用したオペレーションでは、指数バックオフに次の設定を使用します。
設定 | デフォルト値(秒) |
---|---|
自動再試行 | べき等の場合は true |
再試行の最大回数 | 3 |
初期待機時間 | 1 秒 |
反復処理ごとの待機時間乗数 | 2 |
最大待機時間 | 64 秒 |
デフォルトの期限 | 600 秒 |
条件付きべき等である(条件付きで安全に再試行できる)Node.js オペレーションのサブセットがあります。これらのオペレーションは、特定の引数が含まれている場合にのみ再試行されます。
ifGenerationMatch
またはgeneration
- メソッドに
ifGenerationMatch
またはgeneration
がオプションとして渡された場合は、安全に再試行できます。多くの場合、メソッドは一方のパラメータのみ受け入れます。
- メソッドに
ifMetagenerationMatch
ifMetagenerationMatch
がオプションとして渡された場合は、安全に再試行できます。
retryOptions.idempotencyStrategy
はデフォルトで IdempotencyStrategy.RetryConditional
に設定されています。デフォルトの再試行動作を変更する方法の例については、再試行のカスタマイズをご覧ください。
PHP
PHP クライアント ライブラリは、デフォルトで指数バックオフを使用します。
Python
オペレーションでは、デフォルトで次のエラーコードの再試行がサポートされています。
- 接続エラー:
requests.exceptions.ConnectionError
requests.exceptions.ChunkedEncodingError
(アップロードやダウンロードなどペイロード データをフェッチまたは送信するオペレーションのみ)ConnectionError
http.client.ResponseNotReady
urllib3.exceptions.TimeoutError
- HTTP コード:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Python によるオペレーションでは、指数バックオフとして次のデフォルト設定が使用されます。
設定 | デフォルト値(秒) |
---|---|
自動再試行 | べき等の場合は true |
初期待機時間 | 1 |
反復処理ごとの待機時間乗数 | 2 |
最大待機時間 | 60 |
デフォルトの期限 | 120 |
常にべき等である Cloud Storage オペレーションに加えて、Python クライアント ライブラリは、デフォルトで Objects: insert、Objects: delete、Objects: patch を自動的に再試行します。
特定の引数が含まれている場合、条件付きべき等(条件付きで安全に再試行できる)である Python オペレーションのサブセットがあります。これらのオペレーションは、条件のケースに一致した場合にのみ再試行されます。
DEFAULT_RETRY_IF_GENERATION_SPECIFIED
- メソッドに
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 を設定する必要があります。
- メソッドが
Ruby
オペレーションでは、デフォルトで次のエラーコードの再試行がサポートされています。
- 接続エラー:
SocketError
HTTPClient::TimeoutError
Errno::ECONNREFUSED
HTTPClient::KeepAliveDisconnected
- HTTP コード:
408 Request Timeout
429 Too Many Requests
5xx Server Error
Ruby クライアント ライブラリでは、すべての指数バックオフ設定が構成可能です。Ruby クライアント ライブラリを介したオペレーションでは、デフォルトで指数バックオフ用に次の設定が使用されます。
設定 | デフォルト値 |
---|---|
自動再試行 | True |
最大再試行回数 | 3 |
初期待機時間 | 1 秒 |
反復処理ごとの待機時間乗数 | 2 |
最大待機時間 | 60 秒 |
デフォルトの期限 | 900 秒 |
特定の引数が含まれている場合、条件付きべき等(条件付きで安全に再試行できる)である Ruby オペレーションのサブセットがあります。
if_generation_match
またはgeneration
- メソッドに
generation
またはif_generation_match
パラメータが引数として渡された場合は、安全に再試行できます。多くの場合、メソッドはいずれかのパラメータを受け入れます。
- メソッドに
if_metageneration_match
if_metageneration_match
パラメータがオプションとして渡された場合は、安全に再試行できます。
デフォルトでは、すべてのべき等オペレーションは再試行され、条件付きべき等オペレーションは、条件ケースが満たされた場合にのみ再試行されます。べき等以外のオペレーションは再試行されません。デフォルトの再試行動作を変更する方法の例については、再試行のカスタマイズをご覧ください。
REST API
JSON または XML API を直接呼び出す場合は、指数バックオフ アルゴリズムを使用して独自の再試行方法を実装する必要があります。
再試行をカスタマイズする
コンソール
Trusted Cloud コンソールを使用して再試行の動作をカスタマイズすることはできません。
コマンドライン
gcloud storage
コマンドの場合、名前付き構成を作成し、次のプロパティの一部またはすべてを設定することで、再試行方法を制御できます。
設定 | デフォルト値(秒) |
---|---|
base_retry_delay |
1 |
exponential_sleep_multiplier |
2 |
max_retries |
32 |
max_retry_delay |
32 |
次に、コマンドごとに プロジェクト全体のフラグ --configuration
を使用するか、すべての Google Cloud CLI コマンドに gcloud config set
コマンドを使用して定義された構成を適用します。
クライアント ライブラリ
C++
再試行動作をカスタマイズするには、google::cloud::storage::Client
オブジェクトの初期化時に次のオプションを指定します。
google::cloud::storage::RetryPolicyOption
: このライブラリはgoogle::cloud::storage::LimitedErrorCountRetryPolicy
クラスとgoogle::cloud::storage::LimitedTimeRetryPolicy
クラスを提供します。独自のクラスを指定できますが、その場合、google::cloud::RetryPolicy
インターフェースを実装する必要があります。google::cloud::storage::BackoffPolicyOption
: このライブラリはgoogle::cloud::storage::ExponentialBackoffPolicy
クラスを提供します。独自のクラスを指定できますが、その場合、google::cloud::storage::BackoffPolicy
インターフェースを実装する必要があります。google::cloud::storage::IdempotencyPolicyOption
: このライブラリはgoogle::cloud::storage::StrictIdempotencyPolicy
クラスとgoogle::cloud::storage::AlwaysRetryIdempotencyPolicy
クラスを提供します。独自のクラスを指定できますが、その場合、google::cloud::storage::IdempotencyPolicy
インターフェースを実装する必要があります。
詳細については、C++ クライアント ライブラリのリファレンス ドキュメントをご覧ください。
C#
C# クライアント ライブラリで使用されるデフォルトの再試行方法をカスタマイズすることはできません。
Go
ストレージ クライアントを初期化すると、デフォルトの再試行の構成が設定されます。オーバーライドされない限り、構成のオプションはデフォルト値に設定されます。単一のライブラリ呼び出し(BucketHandle.Retryer と ObjectHandle.Retryer を使用)に対して、またはクライアントが行うすべての呼び出し(Client.SetRetry を使用)に対して、デフォルト以外の再試行動作を構成できます。再試行動作を変更するには、該当の RetryOptions をこれらのメソッドのいずれかに渡します。
再試行動作をカスタマイズする方法については、次のコードサンプルをご覧ください。
Java
Storage
を初期化すると、RetrySettings
のインスタンスも初期化されます。オーバーライドされない限り、RetrySettings
のオプションはデフォルト値に設定されます。デフォルトの自動再試行動作を変更するには、Storage
インスタンスの作成に使用する StorageOptions
にカスタム StorageRetryStrategy
を渡します。その他のスカラー パラメータを変更するには、Storage
インスタンスの作成に使用する StorageOptions
にカスタム RetrySettings
を渡します。
再試行動作をカスタマイズする方法については、次の例をご覧ください。
Node.js
Cloud Storage を初期化すると、retryOptions 構成ファイルも初期化されます。オーバーライドされない限り、構成のオプションはデフォルト値に設定されます。デフォルトの再試行動作を変更するには、初期化時にカスタム再試行構成 retryOptions
をストレージ コンストラクタに渡します。Node.js クライアント ライブラリでは、autoRetry
パラメータを使用して、バックオフ方法に沿ったリクエストの再試行を自動的に行えます。
再試行動作をカスタマイズする方法については、次のコードサンプルをご覧ください。
PHP
PHP クライアント ライブラリで使用されるデフォルトの再試行方法をカスタマイズすることはできません。
Python
デフォルトの再試行動作を変更するには、with_XXX
メソッドで呼び出して google.cloud.storage.retry.DEFAULT_RETRY
オブジェクトのコピーを作成します。DEFAULT_RETRY
パラメータを含めると、Python クライアント ライブラリは自動的にバックオフ戦略を使用してリクエストを再試行します。
with_predicate
は、ペイロード データの取得やオブジェクトに送信するオペレーション(アップロードやダウンロードなど)ではサポートされていません。属性は 1 つずつ変更することをおすすめします。詳細については、google-api-core Retry リファレンスをご覧ください。
独自の条件付き再試行を構成するには、ConditionalRetryPolicy
オブジェクトを作成し、カスタム Retry
オブジェクトを DEFAULT_RETRY_IF_GENERATION_SPECIFIED
、DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED
、または DEFAULT_RETRY_IF_ETAG_IN_JSON
でラップします。
再試行動作をカスタマイズする方法については、次のコードサンプルをご覧ください。
Ruby
ストレージ クライアントを初期化すると、すべての再試行構成は上記の表にある値に設定されます。デフォルトの再試行動作を変更するには、ストレージ クライアントを初期化中に再試行構成を渡します。
特定のオペレーションの再試行回数をオーバーライドするには、オペレーションの options
パラメータに retries
を渡します。
REST API
指数バックオフ アルゴリズムを使用して、独自の再試行方法を実装します。
指数バックオフ アルゴリズム
指数バックオフのアルゴリズムは、リクエスト間の待ち時間の間隔を最大バックオフ時間まで増加させながら、指数関数的にリクエストを再試行します。通常は、ジッターと指数バックオフを使用して、レスポンスとべき等性の両方の条件を満たすリクエストを再試行する必要があります。指数バックオフを使用して自動再試行を実装するベスト プラクティスについては、カスケード障害への対応をご覧ください。
再試行のアンチパターン
組み込みの再試行メカニズムを必要に応じて使用またはカスタマイズすることをおすすめします。再試行のカスタマイズをご覧ください。デフォルトの再試行メカニズムを使用している場合でも、カスタマイズしている場合でも、独自の再試行ロジックを実装している場合でも、次の一般的なアンチパターンを避けることが重要です。これらのアンチパターンは、問題を解決するのではなく、悪化させる可能性があります。
バックオフなしで再試行する
リクエストをすぐに再試行したり、非常に短い遅延で再試行したりすると、カスケード障害(他の障害を引き起こす可能性のある障害)が発生する可能性があります。
回避方法: ジッターを伴う指数バックオフを実装します。この戦略では、再試行間の待機時間を徐々に増やし、ランダムな要素を追加して、再試行によってサービスが過負荷になるのを防ぎます。
べき等以外のオペレーションを無条件で再試行する
べき等でないオペレーションを繰り返し実行すると、意図しない副作用(データの意図しない上書きや削除など)が発生する可能性があります。
回避方法: オペレーションのべき等性のセクションで説明されているように、各オペレーションのべき等性の特性を十分に理解します。べき等でないオペレーションの場合は、再試行ロジックで重複を処理できるか、再試行を完全に回避できることを確認してください。競合状態につながる可能性のある再試行には注意してください。
再試行できないエラーを再試行する
すべてのエラーを再試行可能として扱うと、問題が発生する可能性があります。たとえば、認可の失敗や無効なリクエストなどのエラーは永続的であり、根本原因に対処せずに再試行しても成功せず、アプリケーションが無限ループに陥る可能性があります。
回避方法: エラーを一時的なエラー(再試行可能)と永続的なエラー(再試行不可)に分類します。408
、429
、5xx
の HTTP コードや特定の接続の問題など、一時的なエラーのみを再試行します。永続的なエラーの場合は、エラーを記録し、根本原因を適切に処理します。
再試行の上限を無視する
無期限に再試行すると、アプリケーションでリソースが枯渇したり、介入なしでは復元しないサービスにリクエストが継続的に送信される可能性があります。
回避方法: 再試行の上限をワークロードの特性に合わせて調整します。レイテンシが重要なワークロードの場合は、合計最大再試行期間を設定して、レスポンスやエラーをタイムリーに受信できるようにすることを検討してください。バッチ ワークロードの場合、サーバーサイドの一時的なエラーに対する再試行期間が長くなる可能性があるため、再試行回数の上限を高く設定することを検討してください。
不要な再試行のレイヤ化
既存の再試行メカニズムにカスタム アプリケーション レベルの再試行ロジックを追加すると、再試行回数が過剰になる可能性があります。たとえば、アプリケーションがオペレーションを 3 回再試行し、基盤となるクライアント ライブラリもアプリケーションの試行ごとに 3 回再試行する場合、再試行回数は 9 回になります。再試行できないエラーに対して再試行を大量に送信すると、リクエスト スロットリングが発生し、すべてのワークロードのスループットが制限される可能性があります。再試行回数が多いと、成功率が向上しないにもかかわらず、リクエストのレイテンシが増加する可能性があります。
回避方法: 組み込みの再試行メカニズムを使用して構成することをおすすめします。複数のオペレーションにまたがる特定のビジネス ロジックなど、アプリケーション レベルの再試行を実装する必要がある場合は、基盤となる再試行の動作を明確に理解したうえで実装してください。乗数効果を防ぐため、いずれかのレイヤで再試行を無効にするか、大幅に制限することを検討してください。
次のステップ
- リクエストの前提条件の詳細を確認する。