Azure サービスの再試行ガイダンス

ほとんどの Azure サービスとクライアント SDK には、再試行メカニズムが組み込まれています。 しかし、再試行メカニズムは、サービスごとにさまざまな特性や要件があるため一定ではなく、それぞれの再試行メカニズムは特定のサービスに合わせて調整されます。 このガイドでは、ほとんどの Azure サービスの再試行メカニズム機能の概要と、そのサービスに合わせて再試行メカニズムを使用、適合、または拡張するために役立つ情報を記載しています。

一時的なエラーの処理、およびサービスとリソースに対する接続と操作の再試行に関する一般的なガイダンスについては、再試行のガイダンスに関するページをご覧ください。

次の表は、このガイダンスで説明されている Azure サービスの再試行機能をまとめています。

サービス 再試行機能 ポリシーの構成 スコープ テレメトリ機能
Microsoft Entra ID MSAL ライブラリのネイティブ MSAL ライブラリに埋め込み済み 内部 なし
Azure Cosmos DB サービスでネイティブ 構成不可 グローバル TraceSource
Data Lake Store クライアントでネイティブ 構成不可 個々の操作 なし
Event Hubs クライアントでネイティブ プログラムによる Client なし
IoT Hub クライアント SDK でネイティブ プログラムによる Client なし
Azure Cache for Redis クライアントでネイティブ プログラムによる Client TextWriter
Search クライアントでネイティブ プログラムによる Client ETW またはカスタム
Service Bus クライアントでネイティブ プログラムによる 名前空間マネージャー、メッセージング ファクトリ、およびクライアント ETW
Service Fabric クライアントでネイティブ プログラムによる Client なし
ADO.NET を使用した SQL Database Polly 宣言型およびプログラムによる 1 つのステートメントまたはコードのブロック Custom
Entity Framework を使用した SQL Database クライアントでネイティブ プログラムによる AppDomain ごとにグローバル なし
Entity Framework Core を使用した SQL Database クライアントでネイティブ プログラムによる AppDomain ごとにグローバル なし
Storage クライアントでネイティブ プログラムによる クライアントと個々の操作 TraceSource

注意

Azure の組み込み再試行メカニズムのほとんどには、さまざまな種類のエラーや例外に対して異なる再試行ポリシーを適用する方法が現在のところありません。 最適な平均パフォーマンスおよび可用性を提供するポリシーを構成する必要があります。 ポリシーを微調整する 1 つの方法は、ログ ファイルを分析して、発生する一時的エラーの種類を判別することです。

Microsoft Entra ID

Microsoft Entra ID は、コアなディレクトリ サービス、高度な ID ガバナンス、セキュリティ、アプリケーション アクセス管理を結合した包括的な ID およびアクセス管理のクラウド ソリューションです。 Microsoft Entra ID は、一元化されたポリシーとルールに基づいてアプリケーションへのアクセスの制御を実現するための、 ID 管理プラットフォームも開発者に提供します。

Note

マネージド サービス ID エンドポイントにおける再試行ガイダンスについては、トークン取得の Azure VM マネージド サービス ID (MSI) を使用する方法に関するページをご覧ください。

再試行メカニズム

Microsoft Authentication Library (MSAL) には、Microsoft Entra ID 用の再試行メカニズムが組み込まれています。 予想外のロックアウトを避けるためには、サード パーティのライブラリとアプリケーション コードで失敗した接続の再試行を実行せず、MSAL で再試行を処理することを推奨します。

再試行使用のガイダンス

Microsoft Entra ID を使用する場合は、次のガイドラインについて検討してください。

  • 可能であれば、MSAL ライブラリと、組み込みの再試行サポートを使用してください。
  • Microsoft Entra ID 用の REST API を使用している場合は、結果コードが 429 (要求が多すぎます) または 5xx の範囲内のエラーの場合に操作を再試行してください。 その他のエラーの場合は、再試行しないでください。
  • 429 エラーの場合は、Retry-After ヘッダーに示されている時間が経過した後でのみ再試行してください。
  • 5xx エラーの場合は、指数バックオフを使用します。最初の再試行は、応答から 5 秒以上が経過した後です。
  • 429 と 5xx 以外のエラーでは再試行しないでください。

次のステップ

Azure Cosmos DB

Azure Cosmos DB は、スキーマのない JSON データをサポートする完全に管理されたマルチモデル データベースです。 これは構成可能で信頼性の高いパフォーマンスと、ネイティブの JavaScript トランザクション処理を提供し、クラウド用にエラスティックなスケーラビリティを備えて作成されています。

再試行メカニズム

Azure Cosmos DB SDK は特定のエラー条件で自動的に再試行されますが、ユーザー アプリケーションには独自の再試行ポリシーを設定することが推奨されます。 エラー条件と再試行するタイミングの詳細な一覧については、Azure Cosmos DB SDK を使用した回復性があるアプリケーションの設計に関するガイドを参照してください。

テレメトリ

アプリケーションの言語に応じて、操作応答に関するログまたは昇格されたプロパティとして診断とテレメトリが公開されます。 詳細については、Azure Cosmos DB C# SDKAzure Cosmos DB Java SDK の "診断のキャプチャ" に関するセクションを参照してください。

Data Lake Store

Data Lake Storage Gen2 によって、Azure Storage は、Azure 上にエンタープライズ データ レイクを構築するための基盤となります。 Data Lake Storage Gen2 により、大量のデータを簡単に管理できます。

Azure Storage Files Data Lake クライアント ライブラリには、開発者、データ サイエンティスト、アナリストが、さまざまなサイズ、形状、スピードのデータを容易に格納し、さまざまなプラットフォームと言語を使用したあらゆる種類の処理と分析を簡単に実行するために必要な機能がすべて組み込まれています。

再試行メカニズム

DataLakeServiceClient を使用すると、Azure Data Lake サービス リソースとファイル システムを操作できます。 ストレージ アカウントでは、Data Lake サービスに対して最上位の名前空間が提供されます。 クライアントの作成時に、Azure Data Lake サービスに接続するためのクライアント構成オプション (DataLakeClientOptions) を提供できます。 DataLakeClientOptions には、構成可能な (RetryOptions クラス) Retry プロパティ (Azure.Core.ClientOptions から継承) が含まれています。

テレメトリ

Azure Storage の使用とパフォーマンスの監視は、サービスの運用の重要な部分です。 たとえば、頻繁な操作、待機時間の長い操作、サービス側の調整を引き起こす操作などです。

ストレージ アカウントのすべてのテレメトリは、Azure Monitor の Azure Storage のログで確認できます。 この機能により、ストレージ アカウントと Log Analytics およびイベント ハブが統合され、ログを別のストレージ アカウントにアーカイブすることもできます。 メトリックとリソース ログの完全な一覧と、関連付けられているスキーマについては、「Azure Blob Storage 監視データのリファレンス」を参照してください。

Event Hubs

Azure Event Hubs は、数百万のイベントを収集、変換、保存する、ハイパースケールのテレメトリ インジェスト サービスです。

再試行メカニズム

Azure Event Hubs Client Library での再試行動作は、EventHubClient クラスの RetryPolicy プロパティによって制御されます。 既定のポリシーでは、Azure Event Hubs が一時的な EventHubsException または OperationCanceledException を返したときに、エクスポネンシャル バックオフで再試行します。 Event Hubs の既定の再試行ポリシーでは、再試行回数は最大 9 回、エクスポネンシャル バックオフ時間は最大 30 秒です。

EventHubClient client = EventHubClient.CreateFromConnectionString("[event_hub_connection_string]");
client.RetryPolicy = RetryPolicy.Default;

次のステップ

.NET 用 Azure Event Hubs クライアント ライブラリ

IoT Hub

Azure IoT Hub は、デバイスを接続、監視、および管理して、モノのインターネット (IoT) アプリケーションを開発するためのサービスです。

再試行メカニズム

Azure IoT device SDK では、ネットワーク、プロトコル、またはアプリケーションのエラーを検出できます。 エラーの種類に基づき、SDK によって、再試行する必要があるかどうかが判断されます。 "回復可能" なエラーの場合、SDK により、構成済み再試行ポリシーを使用して再試行が開始されます。

既定の再試行ポリシーは "指数バックオフとランダム ジッター" ですが、これは構成することができます。

ポリシーの構成

ポリシーの構成は言語によって異なります。 詳細については、IoT Hub 再試行ポリシーの構成に関するページをご覧ください。

次のステップ

Azure Cache for Redis

Azure Cache for Redis は、一般的なオープン ソース Redis Cache に基づく、高速データ アクセスと低待機時間のキャッシュ サービスです。 これは安全で、Microsoft により管理されており、Azure の任意のアプリケーションからアクセスできます。

このセクションのガイダンスは、StackExchange.Redis クライアントを使用したキャッシュへのアクセスに基づいています。 他の適切なクライアントのリストについては、Redis の Web サイトを参照してください。それらのクライアントは異なる再試行メカニズムを備えている可能性があります。

StackExchange.Redis クライアントは、1 つの接続で多重化を使用することに注意してください。 推奨される使用法は、アプリケーションの起動時にこのクライアントのインスタンスを作成し、そのインスタンスをキャッシュに対するすべての操作に使用するというものです。 このため、キャッシュへの接続が行われるのは 1 回限りであるので、このセクションのすべてのガイダンスは、その初期接続の再試行ポリシーに関連するものとなっており、キャッシュにアクセスする各操作に対するものではありません。

再試行メカニズム

StackExchange.Redis クライアントは、以下を含む一連のオプションで構成される接続マネージャー クラスを使用します。

  • ConnectRetry。 キャッシュに対し失敗した接続を再試行する回数。
  • ReconnectRetryPolicy。 使用する再試行戦略。
  • ConnectTimeout。 最大待機時間 (ミリ秒)。

ポリシーの構成

再試行ポリシーは、キャッシュに接続する前に、クライアントにオプションを設定することで、プログラムによって構成されます。 これは、ConfigurationOptions クラスのインスタンスを作成し、そのプロパティを設定し、それを Connect メソッドに渡すことによって実行できます。

組み込みクラスは、ランダム化された再試行間隔の線形 (一定) 遅延および指数バックオフをサポートします。 IReconnectRetryPolicy インターフェイスを実装することによって、カスタムの再試行ポリシーを作成することもできます。

次の例では、指数バックオフを使用して、再試行戦略を構成します。

var deltaBackOffInMilliseconds = TimeSpan.FromSeconds(5).TotalMilliseconds;
var maxDeltaBackOffInMilliseconds = TimeSpan.FromSeconds(20).TotalMilliseconds;
var options = new ConfigurationOptions
{
    EndPoints = {"localhost"},
    ConnectRetry = 3,
    ReconnectRetryPolicy = new ExponentialRetry(deltaBackOffInMilliseconds, maxDeltaBackOffInMilliseconds),
    ConnectTimeout = 2000
};
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

または、文字列としてオプションを指定して、それを Connect メソッドに渡すこともできます。 ReconnectRetryPolicy プロパティはコードを使用してのみ設定でき、この方法では設定できません。

var options = "localhost,connectRetry=3,connectTimeout=2000";
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

キャッシュに接続する際に、オプションを直接指定することもできます。

var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,connectRetry=3");

詳細については、StackExchange.Redis のマニュアルの Stack Exchange Redis の構成を参照してください。

次の表は、組み込み再試行ポリシーの既定の設定を示しています。

コンテキスト 設定 既定値
(v 1.2.2)
意味
構成オプション ConnectRetry

ConnectTimeout

SyncTimeout

ReconnectRetryPolicy
3

最大 5,000 ミリ秒に SyncTimeout を加算
1000

LinearRetry 5000 ミリ秒
初期接続操作中に接続試行を繰り返す回数。
接続操作のタイムアウト (ミリ秒)。 再試行間の遅延ではありません。
同期操作が許容される時間 (ミリ秒)。

5000 ミリ秒ごとに再試行してください。

注意

同期操作では、SyncTimeout によりエンド ツー エンドの待機時間を追加できますが、設定値が低すぎると、過剰にタイムアウトが発生することがあります。 「Azure Cache for Redis のトラブルシューティング方法」を参照してください。 一般に、同期操作ではなく、非同期操作を使用してください。 詳細については、「Pipelines and Multiplexers (パイプラインとマルチプレクサー)」を参照してください。

再試行使用のガイダンス

Azure Cache for Redis を使用する場合は、次のガイドラインについて検討します。

  • StackExchange Redis クライアントは、その独自の再試行を管理します。ただし、アプリケーションの初回の起動時にキャッシュへの接続を確立するときのみです。 接続タイムアウト、再試行回数、接続の再試行間の間隔を設定できますが、キャッシュに対する操作には再試行ポリシーは適用されません。
  • 多数の再試行を使用するのではなく、元のデータ ソースにアクセスすることによってフォールバックすることを検討してください。

テレメトリ

接続 (他の操作ではない) に関する情報は、 TextWriterを使用して収集できます。

var writer = new StringWriter();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

これが生成する出力の例を次に示します。

localhost:6379,connectTimeout=2000,connectRetry=3
1 unique nodes specified
Requesting tie-break from localhost:6379 > __Booksleeve_TieBreak...
Allowing endpoints 00:00:02 to respond...
localhost:6379 faulted: SocketFailure on PING
localhost:6379 failed to nominate (Faulted)
> UnableToResolvePhysicalConnection on GET
No masters detected
localhost:6379: Standalone v2.0.0, master; keep-alive: 00:01:00; int: Connecting; sub: Connecting; not in use: DidNotRespond
localhost:6379: int ops=0, qu=0, qs=0, qc=1, wr=0, sync=1, socks=2; sub ops=0, qu=0, qs=0, qc=0, wr=0, socks=2
Circular op-count snapshot; int: 0 (0.00 ops/s; spans 10s); sub: 0 (0.00 ops/s; spans 10s)
Sync timeouts: 0; fire and forget: 0; last heartbeat: -1s ago
resetting failing connections to retry...
retrying; attempts left: 2...
...

次のコード例では、StackExchange.Redis クライアントを初期化する際に、再試行と再試行の間の一定 (線形) の待ち時間を構成します。 この例は、ConfigurationOptions のインスタンスを使用して構成を設定する方法を示しています。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace RetryCodeSamples
{
    class CacheRedisCodeSamples
    {
        public async static Task Samples()
        {
            var writer = new StringWriter();
            {
                try
                {
                    var retryTimeInMilliseconds = TimeSpan.FromSeconds(4).TotalMilliseconds; // delay between retries

                    // Using object-based configuration.
                    var options = new ConfigurationOptions
                                        {
                                            EndPoints = { "localhost" },
                                            ConnectRetry = 3,
                                            ReconnectRetryPolicy = new LinearRetry(retryTimeInMilliseconds)
                                        };
                    ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

                    // Store a reference to the multiplexer for use in the application.
                }
                catch
                {
                    Console.WriteLine(writer.ToString());
                    throw;
                }
            }
        }
    }
}

次の例では、オプションを文字列として指定することで、構成を設定しています。 接続タイムアウトとは、キャッシュへの接続での最大待ち期間であり、再試行間の待ち時間ではありません。 なお、ReconnectRetryPolicy プロパティは、コードを使用してのみ設定できます。

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace RetryCodeSamples
{
    class CacheRedisCodeSamples
    {
        public async static Task Samples()
        {
            var writer = new StringWriter();
            {
                try
                {
                    // Using string-based configuration.
                    var options = "localhost,connectRetry=3,connectTimeout=2000";
                    ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(options, writer);

                    // Store a reference to the multiplexer for use in the application.
                }
                catch
                {
                    Console.WriteLine(writer.ToString());
                    throw;
                }
            }
        }
    }
}

詳細な例については、プロジェクト Web サイトの「Configuration (構成)」を参照してください。

次のステップ

Azure Search は、Web サイトまたはアプリケーションへの強力で高度な検索機能の追加、検索結果のすばやく簡単な調整、および微調整された豊富な順位付けモデルの構築を行うために使用できます。

再試行メカニズム

Azure SDK for .NET には、Azure SDK チームの Azure.Search.Documents クライアント ライブラリが含まれています。これは、以前のクライアント ライブラリ Microsoft.Azure.Search と同等の機能を持っています。

Microsoft.Azure.Search の再試行動作を制御するには、SearchServiceClient と SearchIndexClient の各クラスに対する SetRetryPolicy メソッドを使います。 既定のポリシーでは、Azure Search から 5xx または 408 (要求タイムアウト) の応答が返された場合に、指数関数的バックオフによる再試行が行われます。

Azure.Search.Documents の再試行動作を制御するには、プロパティ Retry の SearchClientOptions (SearchClient コンストラクターの一部です) を使います。これはクラス Azure.Core.RetryOptions (すべての構成を使用できます) に属します。

テレメトリ

ETW を使用してトレースするか、カスタム トレース プロバイダーを登録してトレースします。 詳細については、AutoRest のドキュメントを参照してください。

Service Bus

Service Bus は、クラウド メッセージング プラットフォームであり、クラウドまたはオンプレミスでホストされているアプリケーションのコンポーネントに対して、向上したスケーラビリティと回復性を備えた疎結合のメッセージ交換を提供します。

再試行メカニズム

名前空間と一部の構成の詳細は、使用されている Service Bus クライアント SDK パッケージによって異なります。

Package 説明 名前空間
Azure.Messaging.ServiceBus .NET 用の Azure Service Bus クライアント ライブラリ Azure.Messaging.ServiceBus
WindowsAzure.ServiceBus このパッケージは、以前の Service Bus クライアントライブラリです。 これには .Net Framework 4.5.2 が必要です。 Microsoft.Azure.ServiceBus

再試行使用のガイダンス

ServiceBusRetryOptions プロパティは、ServiceBusClient オブジェクトの再試行オプションを指定します。

設定 既定値 意味
CustomRetryPolicy 個々のオプション値の代わりに使用されるカスタムの再試行ポリシー。
遅延 0.8 秒 固定アプローチの再試行間の遅延、またはバックオフベースのアプローチの計算の基準となる遅延。
MaxDelay 60 秒 再試行の間の最大許容遅延。
MaxRetries 3 関連する操作が失敗したと判断するまでの再試行の最大回数です。
モード 指数 再試行の遅延を計算するために使用する方法です。
TryTimeout 60 秒 最初の試行または再試行のどちらであっても、1 回の試行の完了を待機する最大時間。

Mode プロパティを設定して、これらのいずれかの値を使用して ServiceBusRetryMode を構成します。

プロパティ 説明
指数 1 再試行は、バックオフ戦略に基づいて遅延します。この場合、再試行のたびに待機する期間が長くなります。
固定 0 再試行は一定の間隔で行われます。遅延はそれぞれ一定です。

例:

using Azure.Messaging.ServiceBus;

string connectionString = "<connection_string>";
string queueName = "<queue_name>";

// Because ServiceBusClient implements IAsyncDisposable, we'll create it
// with "await using" so that it is automatically disposed for us.
var options = new ServiceBusClientOptions();
options.RetryOptions = new ServiceBusRetryOptions
{
    Delay = TimeSpan.FromSeconds(10),
    MaxDelay = TimeSpan.FromSeconds(30),
    Mode = ServiceBusRetryMode.Exponential,
    MaxRetries = 3,
};
await using var client = new ServiceBusClient(connectionString, options);

テレメトリ

Service Bus は、その他の Azure リソースと同じ種類の監視データを収集します。 Azure Monitor を使用して、Azure Service Bus を監視できます。

Service Bus .NET クライアント ライブラリには、テレメトリを送信するためのさまざまなオプションもあります。

次のコード例は、Azure.Messaging.ServiceBus パッケージを使用して、以下を行う方法を示しています。

  • 新しい ServiceBusClientOptions を使用して、ServiceBusClient の再試行ポリシーを設定する。
  • ServiceBusMessage の新しいインスタンスを使用して新しいメッセージを作成する。
  • ServiceBusSender.SendMessageAsync(message) メソッドを使用して Service Bus にメッセージを送信する。
  • ServiceBusReceivedMessage オブジェクトとして表される ServiceBusReceiver を使用して受信する。
// using Azure.Messaging.ServiceBus;

using Azure.Messaging.ServiceBus;

string connectionString = "<connection_string>";
string queueName = "queue1";

// Because ServiceBusClient implements IAsyncDisposable, we'll create it 
// with "await using" so that it is automatically disposed for us.
var options = new ServiceBusClientOptions();
options.RetryOptions = new ServiceBusRetryOptions
{
    Delay = TimeSpan.FromSeconds(10),
    MaxDelay = TimeSpan.FromSeconds(30),
    Mode = ServiceBusRetryMode.Exponential,
    MaxRetries = 3,
};
await using var client = new ServiceBusClient(connectionString, options);

// The sender is responsible for publishing messages to the queue.
ServiceBusSender sender = client.CreateSender(queueName);
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

await sender.SendMessageAsync(message);

// The receiver is responsible for reading messages from the queue.
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

string body = receivedMessage.Body.ToString();
Console.WriteLine(body);

次のステップ

Service Fabric

Service Fabric クラスターで信頼性の高いサービスを配信することにより、この記事に記載されているほぼすべての潜在的な一時障害を防止できます。 ただ、それでも一部の一時障害は発生します。 たとえば、名前付けサービスでルーティングを変更中に要求を受信すると例外がスローされます。 同じ要求を 100 ミリ秒後に受信すると、要求は成功する可能性が高くなります。

内部的には、Service Fabric が、この種の一時的な障害を管理します。 サービスのセットアップ時に、クラス OperationRetrySettings を使用して一部の設定を構成することができます。 次のコードは例を示します。 ほとんどの場合、既定の設定で対応できるため、このコードは必要ありません。

FabricTransportRemotingSettings transportSettings = new FabricTransportRemotingSettings
{
    OperationTimeout = TimeSpan.FromSeconds(30)
};

var retrySettings = new OperationRetrySettings(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(1), 5);

var clientFactory = new FabricTransportServiceRemotingClientFactory(transportSettings);

var serviceProxyFactory = new ServiceProxyFactory((c) => clientFactory, retrySettings);

var client = serviceProxyFactory.CreateServiceProxy<ISomeService>(
    new Uri("fabric:/SomeApp/SomeStatefulReliableService"),
    new ServicePartitionKey(0));

次のステップ

ADO.NET を使用した SQL Database アクセス

SQL Database は、多様なサイズで利用できるホステッド SQL データベースです。これは Standard (共有) サービスと Premium (非共有) サービスのどちらとしてでも使用できます。

再試行メカニズム

ADO.NET を使用してアクセスする際には、SQL Database には再試行の組み込みサポートはありません。 ただし、要求からのリターン コードを使用して、要求が失敗した理由を判別することができます。 SQL Database の調整の詳細については、「Azure SQL データベースのリソース制限」を参照してください。 関連するエラー コードの一覧については、「SQL Database クライアント アプリケーションの SQL エラー コード」を参照してください。

SQL Database の再試行は、Polly ライブラリを使用して実装できます。 Polly での一時的な障害処理を参照してください。

再試行使用のガイダンス

ADO.NET を使用して SQL Database にアクセスする場合は、次のガイドラインを検討します。

  • 適切なサービス オプション (Shared または Premium) を選択します。 共有インスタンスは、共有サーバーの他のテナントによる使用状況により、通常よりも長い接続遅延や調整の影響を受ける可能性があります。 予測可能性の高いパフォーマンスと信頼性の高い低待機時間での操作が必要な場合は、Premium オプションを選択することを検討してください。
  • データの不整合の原因となる非べき等操作を避けるために、再試行は必ず適切なレベルまたはスコープで実行します。 理想的には、すべての操作はべき等にして、不整合を発生させずに繰り返し実行できるようにする必要があります。 これが当てはまらない場合、再試行は、操作が失敗した場合に、関連するすべての変更を元に戻すことができるレベルまたはスコープで (たとえば 1 トランザクションのスコープ内で) 実行する必要があります。 詳細については、「Cloud Service Fundamentals Data Access Layer – Transient Fault Handling (クラウド サービスの基本データ アクセス層 – 一時的エラー処理)」を参照してください。
  • 固定間隔戦略は、短い間隔でごくわずかな回数の再試行が実行されるのみという対話型のシナリオを除き、Azure SQL Database での使用は推奨されていません。 代わりに、ほとんどのシナリオで、エクスポネンシャル バックオフ戦略を使用することを考慮してください。
  • 接続を定義するときは、接続タイムアウトとコマンド タイムアウトに適切な値を選択します。 タイムアウトが短すぎると、データベースがビジー状態の場合に、接続が途中でエラーになる可能性があります。 タイムアウトが長すぎると、接続エラーを検出するまで長く待ちすぎて、再試行ロジックが正常に機能しなくなる可能性があります。 タイムアウトの値は、エンドツーエンド待機時間の構成要素です。これはすべての再試行向けの再試行ポリシーに指定される再試行遅延に、事実上追加されます。
  • エクスポネンシャル バックオフ再試行ロジックを使用している場合でも、一部の再試行が実行された後は接続を閉じ、新しい接続で操作を再試行します。 同じ接続で同じ操作を複数回再試行することは、接続問題を生じさせる要因となる場合があります。 この技法の例については、「Cloud Service Fundamentals Data Access Layer – Transient Fault Handling (クラウド サービスの基本データ アクセス層 – 一時的エラー処理)」を参照してください。
  • 接続プールが使用中であれば (既定値)、接続を閉じてから再び開いた後であっても、同じ接続がプールから選択される可能性があります。 その場合、解決するための技法は、SqlConnection クラスの ClearPool メソッドを呼び出して、接続を再利用不可とマークすることです。 ただし、これは数回の接続試行が失敗し、問題がある接続に関連した SQL タイムアウト (エラー コード -2) などの、特定クラスの一時的エラーを検出した場合にのみ実行してください。
  • データ アクセス コードが TransactionScope インスタンスとして開始されたトランザクションを使用している場合、再試行ロジックは接続を再度開き、新しいトランザクション スコープを開始する必要があります。 この理由から、再試行可能コード ブロックは、トランザクションのスコープ全体をカバーしている必要があります。

再試行操作を次の設定から始めることを検討してください。 これらの設定は汎用であり、操作を監視して、独自のシナリオに合うように値を微調整する必要があります。

コンテキスト サンプルのターゲット E2E
最大待ち時間
再試行戦略 設定 動作のしくみ
対話型、UI、
またはフォアグラウンド
2 秒 FixedInterval 再試行回数
再試行間隔
最初の高速再試行
3
500 ミリ秒
true
試行 1 - 0 秒の遅延
試行 2 - 500 ミリ秒の遅延
試行 3 - 500 ミリ秒の遅延
バックグラウンド
またはバッチ
30 秒 ExponentialBackoff 再試行回数
最小バックオフ
最大バックオフ
差分バックオフ
最初の高速再試行
5
0 秒
60 秒
2 秒
false
試行 1 - 0 秒の遅延
試行 2 - 最大 2 秒の遅延
試行 3 - 最大 6 秒の遅延
試行 4 - 最大 14 秒の遅延
試行 5 - 最大 30 秒の遅延

注意

エンドツーエンド待機時間のターゲットには、サービスへの接続用の既定のタイムアウトが想定されます。 接続タイムアウトにより長い時間を指定する場合、エンドツーエンド待機時間は、すべての再試行についてこの追加時間分だけ延長されます。

このセクションでは、Polly を使用して、Policy クラスに構成されている再試行ポリシーを使用して Azure SQL Database にアクセスする方法について説明します。

次のコードは、指数バックオフを使用して ExecuteAsync を呼び出す、SqlCommand クラスの拡張メソッドを示しています。

public async static Task<SqlDataReader> ExecuteReaderWithRetryAsync(this SqlCommand command)
{
    GuardConnectionIsNotNull(command);

    var policy = Policy.Handle<Exception>().WaitAndRetryAsync(
        retryCount: 3, // Retry 3 times
        sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(200 * Math.Pow(2, attempt - 1)), // Exponential backoff based on an initial 200 ms delay.
        onRetry: (exception, attempt) =>
        {
            // Capture some information for logging/telemetry.
            logger.LogWarn($"ExecuteReaderWithRetryAsync: Retry {attempt} due to {exception}.");
        });

    // Retry the following call according to the policy.
    await policy.ExecuteAsync<SqlDataReader>(async token =>
    {
        // This code is executed within the Policy

        if (conn.State != System.Data.ConnectionState.Open) await conn.OpenAsync(token);
        return await command.ExecuteReaderAsync(System.Data.CommandBehavior.Default, token);

    }, cancellationToken);
}

この非同期の拡張メソッドは、次のように使用できます。

var sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "[some query]";

using (var reader = await sqlCommand.ExecuteReaderWithRetryAsync())
{
    // Do something with the values
}

次のステップ

Entity Framework 6 を使用した SQL Database アクセス

SQL Database は、多様なサイズで利用できるホステッド SQL データベースです。これは Standard (共有) サービスと Premium (非共有) サービスのどちらとしてでも使用できます。 Entity Framework は、.NET 開発者がドメイン固有オブジェクトを使用してリレーショナル データを操作できるようにする、オブジェクトリレーショナル マッパーです。 これにより、開発者が通常は記述する必要のあるデータアクセス コードの大部分が不要になります。

再試行メカニズム

再試行サポートは、SQL Database データベースに、Entity Framework 6.0 以降で接続回復/再試行ロジックというメカニズムを用いてアクセスするときに提供されます。 再試行メカニズムの主な機能は、次のとおりです。

  • 主要な抽象化は、 IDbExecutionStrategy インターフェイスです。 このインターフェイスは、次の事柄を実行します。
    • 同期および非同期の Execute メソッドを定義します。
    • 既定の戦略として、直接使用できるクラス、またはデータベース コンテキストに基づいて構成できるクラスを定義します。このクラスは、プロバイダー名にマップされるかまたはプロバイダー名とサーバー名にマップされます。 コンテキストに基づいて構成された場合、再試行は個々のデータベース操作のレベルで行われます。特定の 1 コンテキスト操作に対して複数の再試行が行われる場合もあります。
    • 失敗した接続をいつ、どのように再試行するかを定義します。
  • これには、 IDbExecutionStrategy インターフェイスの次のいくつかの組み込み実装が含まれます。
    • 既定値: 再試行なし。
    • SQL Database の既定値 (自動): 再試行なし。ただし例外を検査し、SQL Database 戦略を使用するという提案でそれらをラップします。
    • SQL Database の既定値: Exponential (基本クラスからの継承) に、SQL Database の検出ロジックを加えたもの。
  • ランダム化を含む指数バックオフ戦略を実装します。
  • 組み込み再試行クラスは、ステートフルですが、スレッドセーフではありません。 ただし、このクラスは現在の操作が完了した後に再利用できます。
  • 指定した再試行回数を超えた場合、結果は新しい例外でラップされます。 これは現在の例外をバブルアップしません。

ポリシーの構成

再試行サポートは、Entity Framework 6.0 以降を使用して SQL Database にアクセスする場合に提供されます。 再試行ポリシーは、プログラムにより構成されます。 構成を操作ごとに変更することはできません。

コンテキストに基づいて既定値として戦略を構成する場合は、新しい戦略をオンデマンドで作成する機能を指定します。 次のコードは、 DbConfiguration 基本クラスを拡張する、再試行構成クラスを作成する方法を示しています。

public class BloggingContextConfiguration : DbConfiguration
{
  public BlogConfiguration()
  {
    // Set up the execution strategy for SQL Database (exponential) with 5 retries and 4 sec delay
    this.SetExecutionStrategy(
         "System.Data.SqlClient", () => new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(4)));
  }
}

アプリケーションを起動したときに DbConfiguration インスタンスの SetConfiguration メソッドを使用して、すべての操作に対する既定の再試行戦略として、これを指定することができます。 既定では、EF は構成クラスを自動的に検出して使用します。

DbConfiguration.SetConfiguration(new BloggingContextConfiguration());

コンテキスト クラスに DbConfigurationType 属性で注釈を付けることにより、コンテキストに対して再試行構成クラスを指定できます。 ただし、構成クラスが 1 つしかない場合、EF はコンテキストに注釈を付けずにそれを使用します。

[DbConfigurationType(typeof(BloggingContextConfiguration))]
public class BloggingContext : DbContext

特定の操作に対して異なる再試行戦略を使用する必要があるか、または特定の操作に対する再試行を無効にする必要がある場合、 CallContextにフラグを設定することで、戦略を中断またはスワップできる構成クラスを作成することができます。 構成クラスでは、このフラグを使用して、戦略を切り替えたり、指定した戦略を無効にして既定の戦略を使用したりできます。 詳しくは、実行戦略の中断 (EF6 以降) に関する記事を参照してください。

個々の操作に特定の再試行戦略を使用する別の手法として、必要な戦略クラスのインスタンスを作成し、パラメーターにより目的の設定を指定することができます。 次に、その ExecuteAsync メソッドを呼び出します。

var executionStrategy = new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(4));
var blogs = await executionStrategy.ExecuteAsync(
    async () =>
    {
        using (var db = new BloggingContext("Blogs"))
        {
            // Acquire some values asynchronously and return them
        }
    },
    new CancellationToken()
);

DbConfiguration クラスを使用する最も簡単な方法は、それを DbContext クラスと同じアセンブリ内に配置することです。 ただし、異なるシナリオ (対話型やバックグラウンドでの再試行戦略が異なるなど) で同じコンテキストが必要な場合には、これは適しません。 異なるコンテキストを別の Appdomain で実行する場合は、構成ファイル内で構成クラスを指定するために組み込みサポートを使用するか、またはコードを使用して構成クラスを明示的に設定することができます。 異なる複数のコンテキストを同じ AppDomain 内で実行する必要がある場合には、カスタム ソリューションが必要です。

詳細については、「コード ベースの構成 (EF6 以降)」を参照してください。

次の表は、EF6 を使用している場合の、組み込み再試行ポリシーの既定の設定を示しています。

設定 既定値 意味
ポリシー 指数 指数バックオフ。
MaxRetryCount 5 最大再試行回数。
MaxDelay 30 秒 再試行間の最大遅延。 この値は一連の遅延の計算方法には影響しません。 上限値のみが定義されます。
DefaultCoefficient 1 秒 指数バックオフ計算の係数。 この値は変更できません。
DefaultRandomFactor 1.1 各エントリのランダム遅延を追加するために使用する乗数。 この値は変更できません。
DefaultExponentialBase 2 次の遅延を計算するために使用する乗数。 この値は変更できません。

再試行使用のガイダンス

EF6 を使用して SQL Database にアクセスする場合は、次のガイドラインを検討します。

  • 適切なサービス オプション (Shared または Premium) を選択します。 共有インスタンスは、共有サーバーの他のテナントによる使用状況により、通常よりも長い接続遅延や調整の影響を受ける可能性があります。 予測可能なパフォーマンスと信頼性の高い低待機時間での操作が必要な場合は、Premium オプションを選択することを検討してください。

  • 固定間隔戦略を Azure SQL Database で使用することは推奨されていません。 代わりに、指数バックオフ戦略を使用します。サービスがオーバーロードする可能性があり、遅延が長くなれば回復するための時間をより多くとることができるからです。

  • 接続を定義するときは、接続タイムアウトとコマンド タイムアウトに適切な値を選択します。 タイムアウトは、ビジネス ロジック設計と十分なテストの両方に基づいた値にします。 この値は、時間の経過によるデータの量やビジネス プロセスの変化に応じて、変更することが必要になる場合があります。 タイムアウトが短すぎると、データベースがビジー状態の場合に、接続が途中でエラーになる可能性があります。 タイムアウトが長すぎると、接続エラーを検出するまで長く待ちすぎて、再試行ロジックが正常に機能しなくなる可能性があります。 コンテキストの保存時に実行されるコマンドの数は簡単には特定できないとしても、タイムアウトの値は、エンドツーエンド待機時間の構成要素です。 既定のタイムアウトは、DbContext インスタンスの CommandTimeout プロパティを設定することで変更できます。

  • Entity Framework は、構成ファイルで定義されている再試行構成をサポートします。 ただし、Azure 上で最大の柔軟性を実現するために、アプリケーション内でプログラムを使用して構成を作成することを検討してください。 再試行ポリシーの特定のパラメーター (再試行数や再試行間隔など) は、サービス構成ファイルに格納して、実行時に適切なポリシーを作成するために使用することができます。 これにより、アプリケーションを再起動する必要なく設定を変更できます。

再試行操作を次の設定から始めることを検討してください。 再試行間の遅延を指定することはできません (固定されており、指数のシーケンスとして生成されます)。 カスタム再試行戦略を作成しない限り、ここに示すとおり、指定できるのは最大値のみです。 これらの設定は汎用であり、操作を監視して、独自のシナリオに合うように値を微調整する必要があります。

コンテキスト サンプルのターゲット E2E
最大待ち時間
再試行ポリシー 設定 動作のしくみ
対話型、UI、
またはフォアグラウンド
2 秒 指数 MaxRetryCount
MaxDelay
3
750 ミリ秒
試行 1 - 0 秒の遅延
試行 2 - 750 ミリ秒の遅延
試行 3 - 750 ミリ秒の遅延
バックグラウンド
またはバッチ
30 秒 指数 MaxRetryCount
MaxDelay
5
12 秒
試行 1 - 0 秒の遅延
試行 2 - 最大 1 秒の遅延
試行 3 - 最大 3 秒の遅延
試行 4 - 最大 7 秒の遅延
試行 5 - 12 秒の遅延

注意

エンドツーエンド待機時間のターゲットには、サービスへの接続用の既定のタイムアウトが想定されます。 接続タイムアウトにより長い時間を指定する場合、エンドツーエンド待機時間は、すべての再試行についてこの追加時間分だけ延長されます。

次のコード例は、Entity Framework を使用する単純なデータ アクセス ソリューションを定義します。 これは、DbConfiguration を拡張する BlogConfiguration というクラスのインスタンスを定義することで、特定の再試行戦略を設定します。

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.SqlServer;
using System.Threading.Tasks;

namespace RetryCodeSamples
{
    public class BlogConfiguration : DbConfiguration
    {
        public BlogConfiguration()
        {
            // Set up the execution strategy for SQL Database (exponential) with 5 retries and 12 sec delay.
            // These values could be loaded from configuration rather than being hard-coded.
            this.SetExecutionStrategy(
                    "System.Data.SqlClient", () => new SqlAzureExecutionStrategy(5, TimeSpan.FromSeconds(12)));
        }
    }

    // Specify the configuration type if more than one has been defined.
    // [DbConfigurationType(typeof(BlogConfiguration))]
    public class BloggingContext : DbContext
    {
        // Definition of content goes here.
    }

    class EF6CodeSamples
    {
        public async static Task Samples()
        {
            // Execution strategy configured by DbConfiguration subclass, discovered automatically or
            // or explicitly indicated through configuration or with an attribute. Default is no retries.
            using (var db = new BloggingContext("Blogs"))
            {
                // Add, edit, delete blog items here, then:
                await db.SaveChangesAsync();
            }
        }
    }
}

Entity Framework の再試行メカニズムを使用する他の例については、「接続の回復性と再試行ロジック」を参照してください。

Entity Framework Core を使用した SQL Database アクセス

Entity Framework Core は、.NET Core 開発者がドメイン固有オブジェクトを使用してリレーショナル データを操作できるようにする、オブジェクト リレーショナル マッパーです。 これにより、開発者が通常は記述する必要のあるデータアクセス コードの大部分が不要になります。 このバージョンの Entity Framework は一から作成されているため、EF6.x の機能の一部は自動的に継承されません。

再試行メカニズム

再試行サポートは、SQL Database データベースに接続の弾力性というメカニズム経由で Entity Framework Core を使用してアクセスするときに提供されます。 接続の弾力性は、EF Core 1.1.0 で導入されました。

プライマリの抽象型は、IExecutionStrategy インターフェイスです。 SQL Azure を含む SQL Server の実行戦略では、再試行できる例外タイプが認識されており、最大再試行回数、再試行間の遅延などについて実用的な既定値が設定されています。

次のコードは、データベースとのセッションを表す DbContext オブジェクトを構成するときの自動再試行を実行します。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFMiscellaneous.ConnectionResiliency;Trusted_Connection=True;",
            options => options.EnableRetryOnFailure());
}

次のコードは、実行戦略に従った、自動再試行を使用したトランザクションの実行方法を示しています。 トランザクションは、デリゲート内で定義されています。 一時的な障害が発生した場合、実行戦略は、デリゲートをもう一度呼び出します。

using (var db = new BloggingContext())
{
    var strategy = db.Database.CreateExecutionStrategy();

    strategy.Execute(() =>
    {
        using (var transaction = db.Database.BeginTransaction())
        {
            db.Blogs.Add(new Blog { Url = "https://blogs.msdn.com/dotnet" });
            db.SaveChanges();

            db.Blogs.Add(new Blog { Url = "https://blogs.msdn.com/visualstudio" });
            db.SaveChanges();

            transaction.Commit();
        }
    });
}

Azure Storage

Azure Storage サービスには、Blob Storage、ファイル、ストレージ キューが含まれています。

BLOB、キュー、ファイル

ClientOptions クラスは、すべてのクライアント オプション型の基本データ型であり、Diagnostics、Retry、Transport などの一般的な各種クライアント オプションを公開します。 Azure Queue Storage、Blob Storage、File Storage に接続するためのクライアント構成オプションを提供するには、対応する派生型を使用する必要があります。 次の例では、QueueClientOptions クラス (ClientOptions から派生) を使用して、Azure Queue サービスに接続するようにクライアントを構成します。 Retry プロパティは、再試行の方法や失敗が再試行の対象となるしくみに影響を与えるために指定できるオプションのセットです。

using System;
using System.Threading;
using Azure.Core;
using Azure.Identity;
using Azure.Storage;
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;

namespace RetryCodeSamples
{
    class AzureStorageCodeSamples {

        public async static Task Samples() {

               // Provide the client configuration options for connecting to Azure Queue Storage
                QueueClientOptions queueClientOptions = new QueueClientOptions()
                {
                    Retry = {
                    Delay = TimeSpan.FromSeconds(2),     //The delay between retry attempts for a fixed approach or the delay on which to base
                                                         //calculations for a backoff-based approach
                    MaxRetries = 5,                      //The maximum number of retry attempts before giving up
                    Mode = RetryMode.Exponential,        //The approach to use for calculating retry delays
                    MaxDelay = TimeSpan.FromSeconds(10)  //The maximum permissible delay between retry attempts
                    },

                    GeoRedundantSecondaryUri = new Uri("https://...")
                    // If the GeoRedundantSecondaryUri property is set, the secondary Uri will be used for GET or HEAD requests during retries.
                    // If the status of the response from the secondary Uri is a 404, then subsequent retries for the request will not use the
                    // secondary Uri again, as this indicates that the resource may not have propagated there yet.
                    // Otherwise, subsequent retries will alternate back and forth between primary and secondary Uri.
                };

                Uri queueServiceUri = new Uri("https://storageaccount.queue.core.windows.net/");
                string accountName = "Storage account name";
                string accountKey = "storage account key";

                // Create a client object for the Queue service, including QueueClientOptions.
                QueueServiceClient serviceClient = new QueueServiceClient(queueServiceUri, new DefaultAzureCredential(), queueClientOptions);

                CancellationTokenSource source = new CancellationTokenSource();
                CancellationToken cancellationToken = source.Token;

                // Return an async collection of queues in the storage account.
                var queues = serviceClient.GetQueuesAsync(QueueTraits.None, null, cancellationToken);

テーブル サポート

注意

WindowsAzure.Storage Nuget パッケージと Microsoft.Azure.Cosmos.Table Nuget パッケージは非推奨となりました。 Azure テーブルのサポートについては、「Azure.Data.Tables Nuget パッケージ」を参照してください

再試行メカニズム

クライアント ライブラリは、他のクライアント ライブラリにクロスカット サービスを提供するライブラリである Azure Core ライブラリに基づいています。

クライアント アプリケーションがサービスにネットワーク要求を送信しようとしたときにエラーが発生する理由は数多くあります。 たとえば、タイムアウト、ネットワーク インフラストラクチャの障害、スロットル/ビジーによるサービス要求の拒否、サービスのスケールダウンによるサービス インスタンスの終了、別のバージョンに置き換えられることによるサービス インスタンスのダウン、ハンドルされない例外によるサービスのクラッシュなどがあります。組み込みの再試行メカニズム (コンシューマーがオーバーライドできる既定の構成) を提供することにより、SDK とコンシューマーのアプリケーションでは、この種の障害に対する回復性が高まります。 一部のサービスでは要求ごとに実際の料金が請求されるため、回復性よりもコストを節約したい場合には、コンシューマーが再試行を完全に無効にできる必要があることに注意してください。

ポリシーの構成

再試行ポリシーは、プログラムにより構成されます。 構成は RetryOption クラスに基づいています。 ClientOptions から継承された TableClientOptions に属性があります

      var tableClientOptions = new TableClientOptions();
      tableClientOptions.Retry.Mode = RetryMode.Exponential;
      tableClientOptions.Retry.MaxRetries = 5;
      var serviceClient = new TableServiceClient(connectionString, tableClientOptions);

次の表は、組み込み再試行ポリシーで可能なものを示しています。

RetryOption

設定 意味
遅延 固定アプローチの再試行間の遅延、またはバックオフベースのアプローチの計算の基準となる遅延。 サービスから Retry-After 応答ヘッダーが提示された場合、次の再試行はヘッダー値に指定された期間だけ延期されます。
MaxDelay サービスから Retry-After 応答ヘッダーが提示されない場合の、再試行間隔の最大許容延期期間。 サービスから Retry-After 応答ヘッダーが提示された場合、次の再試行はヘッダー値に指定された期間だけ延期されます。
モード 再試行の遅延を計算するために使用する方法です。
NetworkTimeout 個々のネットワーク操作に適用されるタイムアウト。

RetryMode

設定 意味
指数 再試行は、バックオフ戦略に基づいて遅延します。この場合、再試行のたびに待機する期間が長くなります。
MaxDelay 再試行は一定の間隔で行われます。遅延はそれぞれ一定です。

テレメトリ

ログを表示する最も簡単な方法は、コンソール ログを有効にすることです。 コンソールにメッセージを出力する Azure SDK ログ リスナーを作成するには、AzureEventSourceListener.CreateConsoleLogger メソッドを使用します。

      // Setup a listener to monitor logged events.
      using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

ストレージ エミュレーターをシャットダウンした状態で次のコード例を実行すると、コンソールで再試行に関する情報を確認できます。

using Azure.Core;
using Azure.Core.Diagnostics;
using Azure.Data.Tables;
using Azure.Data.Tables.Models;

namespace RetryCodeSamples
{
    class AzureStorageCodeSamples
    {
        private const string connectionString = "UseDevelopmentStorage=true";
        private const string tableName = "RetryTestTable";

        public async static Task SamplesAsync()
        {
            // Setup a listener to monitor logged events.
            using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

            var tableClientOptions = new TableClientOptions();
            tableClientOptions.Retry.Mode = RetryMode.Exponential;
            tableClientOptions.Retry.MaxRetries = 5;

            var serviceClient = new TableServiceClient(connectionString, tableClientOptions);

            TableItem table = await serviceClient.CreateTableIfNotExistsAsync(tableName);
            Console.WriteLine($"The created table's name is {table.Name}.");
        }
    }
}

一般的な REST および再試行のガイドライン

Azure またはサード パーティ提供のサービスにアクセスする場合は、次の事柄を考慮してください。

  • 再試行の管理に体系的な方法を使用し (再利用可能コードとするなど)、すべてのクライアントとすべてのソリューションの間で一貫性のある方式を適用できるようにします。

  • 対象となるサービスまたはクライアントに再試行メカニズムが組み込まれていない場合は、Polly などの再試行フレームワークを使用して再試行を管理することを検討します。 これは、一貫性のある再試行動作を実装するのに役立ち、ターゲットのサービスに適切な既定の再試行戦略を提供することができます。 ただし、非標準動作を持つサービスと一時的エラーを示す例外に依存しないサービス用に、カスタム再試行コードを作成することが必要になる場合があります。また、再試行動作を管理するために Retry-Response 応答を使用する場合も、カスタム再試行コードの作成が必要になることがあります。

  • 一時的なエラー検出ロジックは、REST 呼び出しの実行に使用する、実際のクライアント API によって異なります。 比較的新しい HttpClient クラスなどの一部のクライアントは、不成功 HTTP 状態コードで完了した要求には例外をスローしません。

  • サービスから返される HTTP 状態コードは、エラーが一時的なものであるかどうかを知るのに役立ちます。 状態コードにアクセスするか、または同等の例外の種類を判別するには、クライアントまたは再試行フレームワークによって生成される例外を調べることが必要になる場合があります。 一般に、次の HTTP コードは、再試行が適切であることを示します。

    • 408 要求タイムアウト
    • 429 Too Many Requests
    • 500 内部サーバー エラー
    • 502 無効なゲートウェイ
    • 503 サービス利用不可
    • 504 ゲートウェイ タイムアウト
  • 再試行ロジックを例外に基づくものにしている場合、次のものは一般に、接続が確立できなかった一時的なエラーを示しています。

    • WebExceptionStatus.ConnectionClosed
    • WebExceptionStatus.ConnectFailure
    • WebExceptionStatus.Timeout
    • WebExceptionStatus.RequestCanceled
  • サービス使用不可状態は、サービスが Retry-After 応答ヘッダーまたは別のカスタム ヘッダーで、再試行前の適切な遅延を示している場合があります。 サービスは、カスタム ヘッダーとして、または応答の内容に埋め込んで、追加情報を送信することもあります。

  • 408 (要求タイムアウト) および 429 (要求が多すぎます) を除き、クライアント エラー (4xx の範囲内のエラー) を表す状態コードに対しては再試行しないでください。

  • 再試行戦略および再試行メカニズムは、多様なネットワーク状態やさまざまなシステム負荷などの幅広い条件下で十分にテストします。

再試行戦略

次に示すのは、標準的な種類の再試行戦略間隔です。

  • Exponential。 指定回数の再試行を実行し、ランダムな指数バックオフ アプローチを使用して再試行間の間隔を決定する再試行ポリシーです。 次に例を示します。

    var random = new Random();
    
    var delta = (int)((Math.Pow(2.0, currentRetryCount) - 1.0) *
                random.Next((int)(this.deltaBackoff.TotalMilliseconds * 0.8),
                (int)(this.deltaBackoff.TotalMilliseconds * 1.2)));
    var interval = (int)Math.Min(checked(this.minBackoff.TotalMilliseconds + delta),
                    this.maxBackoff.TotalMilliseconds);
    retryInterval = TimeSpan.FromMilliseconds(interval);
    
  • Incremental。 指定回数の再試行を実行し、再試行ごとに時間間隔を長くする再試行戦略です。 次に例を示します。

    retryInterval = TimeSpan.FromMilliseconds(this.initialInterval.TotalMilliseconds +
                    (this.increment.TotalMilliseconds * currentRetryCount));
    
  • LinearRetry。 指定回数の再試行を実行し、再試行間には指定の固定時間間隔を使用する再試行ポリシーです。 次に例を示します。

    retryInterval = this.deltaBackoff;
    

Polly での一時的な障害処理

Polly は、再試行およびサーキット ブレーカー戦略をプログラムで処理するライブラリです。 Polly プロジェクトは、.NET Foundation のメンバーです。 クライアントがネイティブで再試行をサポートしないサービスでは、Polly は有効な代替手段で、正しく実装することが難しい可能性もある、カスタム再試行コードを書く必要がなくなります。 Polly でも、再試行をログに記録できるよう、エラーを追跡する方法が提供されています。

次のステップ