Azure Storage クライアント ライブラリの再試行ポリシーに関する推奨事項
このポストは、5 月 22 日に投稿した Azure Storage Client Library Retry Policy Recommendations の翻訳です。
Azure Storage クライアント ライブラリ (SCL) の再試行ポリシーをどのように構成するかについては、Gaurav Mantri が執筆した「SCL 2.0 – 再試行ポリシーの実装 (英語)」でわかりやすく説明されています。しかし、どの再試行ポリシーの設定を使用すればよいかの実践的な解説は、なかなかありません。この記事では、マイクロソフトのチームが高負荷シナリオで SCL を実際に使用した経験に基づいて、推奨事項をお伝えします (低負荷シナリオについては、既定の再試行ポリシーで十分に機能します)。
ExponentialRetry と LinearRetry
応答時間を短くすることを考慮する必要がないバッチ処理では、ExponentialRetry (英語) クラスを使用するとよさそうに思いがちです。一時的なエラーを可能な限りすばやく解決するために再試行を迅速に行い、同時に、障害が発生しているサービスの問題が拡大することを防ぐため、サーバーには過大な負荷を掛けないようにしたいと考えるでしょう。
しかし、ここで Storage サービスへの接続品質を追跡できるようにしておくことの必要性について検討してください。タイムアウト時間を非常に長く設定したまま ExponentialRetry (英語) で何度も再試行すると、ほとんどの一時的なエラーについて、例外への対応は不要になりますが、その一方で、問題が頻繁に発生した場合にそれを把握することができません。応答時間は追跡できますが、問題の原因が一時的なエラーかどうかまではわかりません。
このため、より詳細な診断情報を得るには、LinearRetry (英語) クラスの使用が最適です。再試行の間隔を相対的に短くして、回数を数回のみに限定すると、試行はかなり短い時間で失敗します。これによりユーザーが例外を把握し、障害のレポートを作成しつつバックオフを実装できます。ほとんどの要求を最終的に正常に完了させるには、このバックオフが非常に重要です。
MaximumExecutionTime
IRequestOptions (英語) インターフェイスに、MaximumExecutionTime (英語) プロパティもあります。この値には、すべての再試行処理が終了するまでの時間の上限を設定します。大規模な処理は失敗するまでにある程度の時間を要するため、実行する処理の種類によっては、非常に大きな値を設定する必要があります。チームでは、高負荷条件下で大規模な処理が要求された場合は、この値が 10 秒未満の場合に頻繁にエラーが発生することを確認しました。MaximumExecutionTime を 60 秒に設定すると、このような例外を回避できます。ただし、これが有効なのはバックグラウンド処理の場合で、ユーザーが操作する処理の場合には調整が必要です。
また、チームでは、ServerTimeout (英語) および再試行の最大回数 (英語) の値は、比較的影響が小さいことを確認しました。これらの値は、それぞれ 5 秒と 10 回に設定するとうまく動作しました。繰り返しになりますが、これは応答の迅速性よりも最終的な処理の成功を優先させるバックグラウンド処理の場合に当てはまることです。
不要な作業の回避
一部の処理では、SCL API で IfExists メソッドが提供されています。これを使用すると、次の例のように例外を回避することができます。
foreach (IListBlobItem blobItem in this.BlobList())
{
CloudBlockBlob cloudBlob = (CloudBlockBlob)blobItem;
cloudBlob.DeleteIfExists(options: this.requestOptions);
}
このプログラムは十分に堅牢であるように見えますし、実際にそうなのですが、失敗が発生する頻度が高くなり、トラフィック量も増加します。マイクロソフトが実施したストレス テストでは、頻繁に失敗が発生しました。また、アイテムが存在しているかどうかを把握する必要はありません。DeleteIfExists (英語) ではなく Delete (英語) を呼び出すようにコードを変更すると、処理のパフォーマンスが向上すると共に、失敗の発生頻度が低下します。このため、既知の情報を使用して、トラフィック量を減少させると共に失敗の発生頻度を低下させることを推奨します。
例外処理
対応力の高い再試行ポリシーを構築しても、エラーが長時間存続し、例外処理が必要となる場合があります。Azure Storage クライアント フレームワークでは、StorageException (英語) または System.AggregateException を使用すると、エラーの内容を確認できます。
また、この再試行ポリシーのクラスでは、400 番台のステータス コードの再試行を実行しません。この他に、現時点では 306、501、505 でも同様です。これらのステータス コードは、エラーが一時的なものではなく、ユーザーの対応が必要であることを示しています。その一般的な例としては、404 (not found) や 409 (conflict) が挙げられます。再試行ポリシーをカスタマイズする場合は、このような状況の確認を確実に行ってください。
ラッパー ライブラリは不要
マイクロソフトでは、必要な再試行処理をラッパー ライブラリが実行するように Azure Storage クライアントを設計する予定でしたが、最終的にはこれが不要になりました。チームでは引き続き、再試行の微調整とエラー処理を一元化するビジネス ロジック用のライブラリを作成していますが、これは Azure Storage クライアントのコードを基礎とするものになる予定です。
この記事に使用するコンテンツの提供とテストの実施について、Allen Prescott に感謝の意を表します。