Azure SDK for Java におけるリトライについて
前回につづいてリトライについてです。
オンプレ環境でアプリケーションを実装している時は、リトライなど気していなかった人も多かったのではないかと思いますが、Azure などのクラウド環境上では、メンテナンスによってサービスが再起動したり、ネットワークの中断なども顕著に発生するため、リトライの実装は必須になっております。
Azure のドキュメントに、「Azure サービスの再試行ガイダンス」というものがありますので、まずはこれを読みましょう、必読です。ここには、各コンポーネントと SDK がどういうリトライを行っているか説明されています。
Azure サービスの再試行ガイダンス - Best practices for cloud applications | Microsoft Docs
Cosmos DB
先ほどのドキュメントにある表をみると、「サービスでネイティブ」 かつ、 ポリシーは「構成不可」を書かれていて、いまいちピンときません。他が「クライアントでネイティブ」と書かれているところから類推すればクライアントSDKではなく、Cosmos DBがサービスレベルでなんかしてくれるようにも読めます。
また、Cosmos DBの再試行メカニズムの章をよむと、スロットリングに関連したリトライの設定はできそうです。文書ではC#の例ですが、Javaでは、ThrottlingRetryOptions
で指定できます。
では、他の場合はどのようなリトライをしているのでしょうか。気になるので SDKのソースを探索してみました。
ClientRetryPolicy#shouldRetry
が定義されていて、そこに色々なケースでリトライの可否を判定しています。
リトライすべきかどうかは、SDKが適切に判定してくれるということで、実装はちゃんとされているので安心して利用できます。心配性な人は、SDKを読み込んで検証してみてください。リトライは、なかなか再現できないのがつらいところですけど。
また、Javaの話でいえば、いかにもリトライの記述があって、
Azure Cosmos DB Java SDK v4 の診断およびトラブルシューティング | Microsoft Docs
引用すると、
- 読み取りおよびクエリ IO エラーは、エンド ユーザーにはわからないまま SDK によって再試行されます。
- 書き込み (Create、Upsert、Replace、Delete) はべき等では "なく"、したがって SDK は必ずしも無条件に、失敗した書き込み操作を再試行できるわけではありません。 エラーを処理して再試行するには、ユーザーのアプリケーション ロジックが必要です
とのことなので、利用する際は注意してください。
Storage Blob
次はストレージです。表では、「クライアントでネイティブ」、ポリシーの構成には「プログラムによる」と書かれています。
ストレージには、その名の通り RequestRetryOptions
クラスが用意されていり、クライアントインスタンスをビルドするときに設定できます。デフォルト時の動作は、ハードコーディングされていて、指数関数タイプの4回くらいの感じになっています。デフォルト設定でも問題ないと思います。
自力記述するときは以下のような感じになります。
RequestRetryOptions retry = new RequestRetryOptions(
RetryPolicyType.EXPONENTIAL,
3, // max tries
3, // time out in seconds
5000L, // retry delay milli seconds
60000L, // max retry delay milli seconds
null);
BlobServiceAsyncClient storageClient = new BlobServiceClientBuilder()
.retryOptions(retry)
.buildAsyncClient();
SDKでは以下のあたりで、リトライしているっぽいです。軽くソースを見た限り、リトライ回数はみているけど、ディレイとかは独自に計算していて、Optionの意味がよく分らない感じでした。
まとめ
ということで、いくつかのSDKについて、リトライについてまとめてみました。ドキュメントは豊富にありますが、言語毎にとっちらかっている印象は拭えません。地道にググり、最終的にはSDKのソースにあたりましょう。また、マイクロソフトのドキュメントでは、リトライの訳語が「再試行」で統一されているようですので、「再試行」でググった方がいいかもしれません。