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

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

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

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

サービス 再試行機能 ポリシーの構成 スコープ テレメトリ機能
Azure Active Directory MSAL ライブラリのネイティブ MSAL ライブラリに埋め込み済み 内部 なし
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 つの方法は、ログ ファイルを分析して、発生する一時的エラーの種類を判別することです。

Azure Active Directory

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

注意

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

再試行メカニズム

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

再試行使用のガイダンス

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

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

詳細情報

Cosmos DB

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

再試行メカニズム

CosmosClient クラスによって、失敗した試行が自動的にもう一度実行されます。 再試行回数と最大待機時間を設定するには、CosmosClientOptions を構成します。 クライアントがスローする例外は、再試行ポリシーを超えているか、一時的なエラーでないかのいずれかです。 クライアントが Cosmos DB によってスロットルされると、HTTP 429 エラーが返されます。 CosmosException クラスで状態コードを確認します。

ポリシーの構成

次の表は、CosmosClientOptions クラスの既定の設定を示しています。

設定 既定値 説明
MaxRetryAttemptsOnRateLimitedRequests 9 Cosmos DB によってクライアントに対してレート制限が適用されたために要求が失敗した場合の最大再試行回数。
MaxRetryWaitTimeOnRateLimitedRequests 30 Azure Cosmos DB サービスの再試行の最大待機時間 (秒)。

CosmosClient cosmosClient = new CosmosClient("connection-string", new CosmosClientOptions()
{
    MaxRetryAttemptsOnRateLimitedRequests = 5,
    MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(15)
});

テレメトリ

再試行回数は、.NET TraceSource により、構造化されていないトレース メッセージとしてログに記録されます。 イベントをキャプチャし、それらを適切な宛先ログに書き込むには、TraceListener を構成する必要があります。

たとえば、次のコードを App.config ファイルに追加すると、同じ場所のテキスト ファイルに、実行可能ファイルとしてトレースが生成されます。

<configuration>
  <system.diagnostics>
    <switches>
      <add name="SourceSwitch" value="Verbose"/>
    </switches>
    <sources>
      <source name="DocDBTrace" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch" >
        <listeners>
          <add name="MyTextListener" type="System.Diagnostics.TextWriterTraceListener" traceOutputOptions="DateTime,ProcessId,ThreadId" initializeData="CosmosDBTrace.txt"></add>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

Event Hubs

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

再試行メカニズム

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

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

詳細情報

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

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

テレメトリ

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

Service Bus

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

再試行メカニズム

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

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

どちらのバージョンのクライアント ライブラリにも、次の RetryPolicy 組み込み実装が用意されています。

  • RetryExponential。 エクスポネンシャル バックオフが実装されています。

  • NoRetry。 再試行は実行されません。 このクラスは、Service Bus API レベルでの再試行が不要な場合、たとえば、再試行がバッチまたは複数ステップ操作の一部として他のプロセスによって管理されている場合に使用します。

RetryPolicy.Default プロパティによって、型 RetryExponential の既定のポリシーが返されます。 このポリシー オブジェクトには、次の設定があります。

設定 既定値 意味
MinimalBackoff 0 最小バックオフ間隔。 deltaBackoff から計算された再試行間隔に追加されます。
MaximumBackoff 30 秒 最大バックオフ間隔。
DeltaBackoff 3 秒 再試行のバックオフ間隔。 この期間の倍数は、後続の再試行に使用されます。
MaxRetryCount 5 最大再試行回数。 (WindowsAzure.ServiceBus パッケージでは既定値は 10。)

さらに、古い WindowsAzure.ServiceBus パッケージでは次のプロパティが定義されています。

設定 既定値 意味
TerminationTimeBuffer 5 秒 残り時間がこの値を下回ると再試行は中止されます。

Service Bus のアクションにより、さまざまな例外 (「Service Bus メッセージングの例外」を参照) が返される可能性があります。 Service Bus から返される例外は IsTransient プロパティを公開し、これはクライアントが操作を再試行するかどうかを示します。 このプロパティは、組み込みの RetryExponential ポリシーによって再試行前に確認されます。

検出された最後の例外が ServerBusyException の場合、RetryExponential ポリシーによって、計算された再試行間隔に 10 秒が追加されます。 この値は変更できません。

カスタム実装では、例外タイプと IsTransient プロパティの組み合わせを使用して、再試行アクションをより細かく制御することができます。 たとえば、 QuotaExceededException を検出した場合に、キューへのメッセージの送信を再試行する前に、キューを排出するアクションを実行することができます。

次のコードは、Microsoft.Azure.ServiceBus ライブラリを使用して、Service Bus クライアントの再試行ポリシーを設定します。

const string QueueName = "queue1";
const string ServiceBusConnectionString = "<your_connection_string>";

var policy = new RetryExponential(
    minimumBackoff: TimeSpan.FromSeconds(10),
    maximumBackoff: TimeSpan.FromSeconds(30),
    maximumRetryCount: 3);
var queueClient = new QueueClient(ServiceBusConnectionString, QueueName, ReceiveMode.PeekLock, policy);

再試行ポリシーは、個々の操作レベルで設定することはできません。 これはクライアントのすべての操作に適用されます。

再試行使用のガイダンス

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

  • 組み込みの RetryExponential 実装を使用する際には、ポリシーがサーバー ビジー例外に反応し、適切な再試行モードに自動的に切り替えるので、フォールバック操作を実装しないでください。
  • Service Bus は、組み合わせ名前空間という機能をサポートします。これは、プライマリ名前空間内のキューでエラーが発生した場合の、別の名前空間内にあるバックアップ キューへの自動フェールオーバーを実装します。 セカンダリ キューからのメッセージは、プライマリ キューが回復したらそこに送り戻すことができます。 この機能は、一時的なエラーに対処するために役立ちます。 詳細については、「非同期メッセージング パターンと高可用性」を参照してください。

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

Context 最大待機時間の例 再試行ポリシー 設定 しくみ
対話型、UI、またはフォアグラウンド 2 秒* 指数 MinimumBackoff = 0
MaximumBackoff = 30 秒
DeltaBackoff = 300 ミリ秒
TimeBuffer = 300 ミリ秒
MaxRetryCount = 2
試行 1: 0 秒の遅延
試行 2: 最大 300 ミリ秒の遅延
試行 3: 最大 900 ミリ秒の遅延
バックグラウンドまたはバッチ 30 秒 指数 MinimumBackoff = 1
MaximumBackoff = 30 秒
DeltaBackoff = 1.75 秒
TimeBuffer = 5 秒
MaxRetryCount = 3
試行 1: 最大 1 秒の遅延
試行 2: 最大 3 秒の遅延
試行 3: 約 6 秒の遅延
試行 4: 約 13 秒の遅延

* サーバー ビジー応答を受信した場合に追加される遅延は含まれません。

テレメトリ

Service Bus は、再試行を ETW イベントとして EventSource を使ってログに記録します。 イベントをキャプチャしてパフォーマンス ビューアーに表示したり、イベントを適切な宛先ログに書き込んだりするには、 EventListener をイベント ソースにアタッチする必要があります。 再試行イベントは、次の形式です。

Microsoft-ServiceBus-Client/RetryPolicyIteration
ThreadID="14,500"
FormattedMessage="[TrackingId:] RetryExponential: Operation Get:https://retry-tests.servicebus.windows.net/TestQueue/?api-version=2014-05 at iteration 0 is retrying after 00:00:00.1000000 sleep because of Microsoft.ServiceBus.Messaging.MessagingCommunicationException: The remote name could not be resolved: 'retry-tests.servicebus.windows.net'.TrackingId:6a26f99c-dc6d-422e-8565-f89fdd0d4fe3, TimeStamp:9/5/2014 10:00:13 PM."
trackingId=""
policyType="RetryExponential"
operation="Get:https://retry-tests.servicebus.windows.net/TestQueue/?api-version=2014-05"
iteration="0"
iterationSleep="00:00:00.1000000"
lastExceptionType="Microsoft.ServiceBus.Messaging.MessagingCommunicationException"
exceptionMessage="The remote name could not be resolved: 'retry-tests.servicebus.windows.net'.TrackingId:6a26f99c-dc6d-422e-8565-f89fdd0d4fe3,TimeStamp:9/5/2014 10:00:13 PM"

次のコード例は、以下に対する再試行ポリシーの設定方法を示しています。

  • 名前空間マネージャー。 ポリシーは、そのマネージャー上のすべての操作に適用されます。個々の操作向けにオーバーライドすることはできません。
  • メッセージング ファクトリ。 ポリシーは、このファクトリから作成されたすべてのクライアントに適用されます。個々のクライアントの作成時にオーバーライドすることはできません。
  • 個々のメッセージング クライアント クライアントの作成後に、そのクライアントに再試行ポリシーを設定することができます。 ポリシーは、そのクライアント上のすべての操作に適用されます。
using System;
using System.Threading.Tasks;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;

namespace RetryCodeSamples
{
    class ServiceBusCodeSamples
    {
        private const string connectionString =
            @"Endpoint=sb://[my-namespace].servicebus.windows.net/;
                SharedAccessKeyName=RootManageSharedAccessKey;
                SharedAccessKey=C99..........Mk=";

        public async static Task Samples()
        {
            const string QueueName = "TestQueue";

            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;

            var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);

            // The namespace manager will have a default exponential policy with 10 retry attempts
            // and a 3 second delay delta.
            // Retry delays will be approximately 0 sec, 3 sec, 9 sec, 25 sec and the fixed 30 sec,
            // with an extra 10 sec added when receiving a ServiceBusyException.

            {
                // Set different values for the retry policy, used for all operations on the namespace manager.
                namespaceManager.Settings.RetryPolicy =
                    new RetryExponential(
                        minBackoff: TimeSpan.FromSeconds(0),
                        maxBackoff: TimeSpan.FromSeconds(30),
                        maxRetryCount: 3);

                // Policies cannot be specified on a per-operation basis.
                if (!await namespaceManager.QueueExistsAsync(QueueName))
                {
                    await namespaceManager.CreateQueueAsync(QueueName);
                }
            }

            var messagingFactory = MessagingFactory.Create(
                namespaceManager.Address, namespaceManager.Settings.TokenProvider);
            // The messaging factory will have a default exponential policy with 10 retry attempts
            // and a 3 second delay delta.
            // Retry delays will be approximately 0 sec, 3 sec, 9 sec, 25 sec and the fixed 30 sec,
            // with an extra 10 sec added when receiving a ServiceBusyException.

            {
                // Set different values for the retry policy, used for clients created from it.
                messagingFactory.RetryPolicy =
                    new RetryExponential(
                        minBackoff: TimeSpan.FromSeconds(1),
                        maxBackoff: TimeSpan.FromSeconds(30),
                        maxRetryCount: 3);


                // Policies cannot be specified on a per-operation basis.
                var session = await messagingFactory.AcceptMessageSessionAsync();
            }

            {
                var client = messagingFactory.CreateQueueClient(QueueName);
                // The client inherits the policy from the factory that created it.


                // Set different values for the retry policy on the client.
                client.RetryPolicy =
                    new RetryExponential(
                        minBackoff: TimeSpan.FromSeconds(0.1),
                        maxBackoff: TimeSpan.FromSeconds(30),
                        maxRetryCount: 3);

                // Policies cannot be specified on a per-operation basis.
                var session = await client.AcceptMessageSessionAsync();
            }
        }
    }
}

詳細情報

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
}

詳細情報

SQL Database を最大限活用するための一般的なガイダンスについては、Azure SQL Database パフォーマンス/弾力性に関するガイドを参照してください。

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 パッケージは非推奨になりました。 Azure のテーブル サポートについては、Microsoft.Azure.Cosmos.Table NuGet パッケージを参照してください。

再試行メカニズム

再試行は、個々の REST 操作レベルで実行され、クライアント API 実装の不可欠な部分です。 クライアント ストレージ SDK は、 IExtendedRetryPolicy インターフェイスを実装するクラスを使用します。

組み込みクラスは、Linear (一定遅延) と、ランダム化された再試行間隔が指定される Exponential をサポートします。 別のプロセスがより高いレベルで再試行を処理している場合に使用する、再試行なしポリシーもあります。 ただし、組み込みクラスによって提供されていない特定の要件がある場合は、独自の再試行クラスを実装できます。

代替再試行では、読み取りアクセス geo 冗長ストレージ (RA-GRS) を使用しており、要求の結果が再試行可能エラーになる場合は、プライマリとセカンダリのストレージ サービス場所での切り替えが行われます。 詳細については、「Azure Storage 冗長オプション」を参照してください。

ポリシーの構成

再試行ポリシーは、プログラムにより構成されます。 一般的なプロシージャでは、TableRequestOptionsBlobRequestOptionsFileRequestOptions、または QueueRequestOptions の各インスタンスが作成されて設定されます。

TableRequestOptions interactiveRequestOption = new TableRequestOptions()
{
  RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(500), 3),
  // For Read-access geo-redundant storage, use PrimaryThenSecondary.
  // Otherwise set this to PrimaryOnly.
  LocationMode = LocationMode.PrimaryThenSecondary,
  // Maximum execution time based on the business use case.
  MaximumExecutionTime = TimeSpan.FromSeconds(2)
};

要求オプション インスタンスは、クライアントに対して設定することができ、そのクライアントからのすべての操作は、指定された要求オプションを使用します。

client.DefaultRequestOptions = interactiveRequestOption;
var stats = await client.GetServiceStatsAsync();

クライアント要求オプションは、要求オプション クラスの設定済みインスタンスを操作メソッドのパラメーターとして渡すことによって、オーバーライドできます。

var stats = await client.GetServiceStatsAsync(interactiveRequestOption, operationContext: null);

OperationContext インスタンスは、再試行が行われたときと操作が完了したときに実行するコードの指定に使用できます。 このコードは、ログとテレメトリで使用する、操作に関する情報を収集できます。

// Set up notifications for an operation
var context = new OperationContext();
context.ClientRequestID = "some request id";
context.Retrying += (sender, args) =>
{
    // Collect retry information
};
context.RequestCompleted += (sender, args) =>
{
    // Collect operation completion information
};
var stats = await client.GetServiceStatsAsync(null, context);

さらに、エラーに対して再試行が適切であるかどうかを示すために、拡張再試行ポリシーは、再試行回数、前回の要求の結果、次回の再試行が行われる場所 (プライマリまたはセカンダリ) を示す、 RetryContext オブジェクトを返します (詳細については、次の表を参照してください)。 RetryContext オブジェクトのプロパティは、再試行を行うかどうか、およびいつ行うかを決定するために使用できます。 詳細については、IExtendedRetryPolicy.Evaluate メソッドを参照してください。

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

要求のオプション:

設定 既定値 意味
MaximumExecutionTime なし 要求の最大実行時間 (考えられるすべての再試行が含まれます)。 指定しない場合、要求が許可されるのにかかる時間に制限がなくなります。 つまり、要求が応答しなくなることがあります。
ServerTimeout なし 要求のサーバー タイムアウト間隔 (値は秒単位に丸められます)。 指定しない場合、サーバーに対するすべての要求に既定値が使用されます。 通常、この設定を省略してサーバーの既定値が使用されるようにすることが最善のオプションになります。
LocationMode なし ストレージ アカウントが読み取りアクセス geo 冗長ストレージ (RA-GRS) のレプリケーション オプションを指定して作成されている場合、場所モードを使用して、要求を受け取る場所を示すことができます。 たとえば、PrimaryThenSecondary を指定した場合、要求は必ず最初にプライマリの場所に送信されます。 失敗した場合、要求はセカンダリの場所に送信されます。
RetryPolicy ExponentialPolicy 各オプションの詳細については、以下をご覧ください。

Exponential ポリシー:

設定 既定値 意味
maxAttempt 3 再試行回数。
deltaBackoff 4 秒 再試行のバックオフ間隔。 この期間のランダムな倍数が、後続の再試行に使用されます。
MinBackoff 3 秒 deltaBackoff から計算されたすべての再試行間隔に追加されます。 この値は変更できません。
MaxBackoff 120 秒 MaxBackoff は、計算された再試行間隔が MaxBackoff より大きい場合に使用されます。 この値は変更できません。

Linear ポリシー:

設定 既定値 意味
maxAttempt 3 再試行回数。
deltaBackoff 30 秒 再試行のバックオフ間隔。

再試行使用のガイダンス

ストレージ クライアント API を使用して Microsoft Azure Storage サービスにアクセスする場合は、次のガイドラインを検討します。

  • Microsoft.Azure.Storage.RetryPolicies 名前空間からの組み込み再試行ポリシーを使用します (これらのポリシーが要件に適している場合)。 ほとんどの場合、これらのポリシーで十分対応できます。

  • バッチ操作、バックグラウンド タスク、または非対話型のシナリオでは、ExponentialRetry ポリシーを使用します。 これらのシナリオでは、一般に、サービスを復旧するためにより多くの時間を確保できます—結果として、操作は最終的に成功する可能性が高くなります。

  • 合計実行時間を制限するには、RequestOptions パラメーターの MaximumExecutionTime プロパティを指定することを検討してください。ただし、タイムアウト値を選択する場合は、操作の種類とサイズを考慮に入れてください。

  • カスタム再試行を実装する必要がある場合は、ストレージ クライアント クラスを囲むラッパーは作成しないでください。 代わりに IExtendedRetryPolicy インターフェイスから、既存のポリシーを拡張する機能を使用してください。

  • 読み取りアクセス geo 冗長ストレージ (RA-GRS) を使用している場合、 LocationMode を使用して、プライマリへのアクセスが失敗した場合に、再試行がストアのセカンダリ読み取り専用コピーにアクセスするように指定できます。 ただし、このオプションを使用するときは、プライマリ ストアからのレプリケーションがまだ完了していない場合に、古くなった可能性があるデータを用いてアプリケーションが正常に動作できることを確認する必要があります。

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

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

テレメトリ

再試行回数は TraceSource に記録されます。 イベントをキャプチャし、それらを適切な宛先ログに書き込むには、TraceListener を構成する必要があります。 データをログ ファイルに書き込むには TextWriterTraceListener または XmlWriterTraceListener を、Windows イベント ログに書き込むには EventLogTraceListener を、トレース データを ETW サブシステムに書き込むには EventProviderTraceListener をそれぞれ使用できます。 バッファーの自動フラッシュと、ログに記録するイベントの詳細度 (たとえば、エラー、警告、情報、および冗長など) を構成することもできます。 詳細については、「 .NET ストレージ クライアント ライブラリによるクライアント側のログ」を参照してください。

操作は OperationContext インスタンスを受け取る可能性があります。これはカスタム テレメトリ ロジックをアタッチするために使用できる Retrying イベントを公開します。 詳細については、「OperationContext.Retrying Event (OperationContext.Retrying イベント)」を参照してください。

次のコード例は、異なる再試行設定で 2 つの TableRequestOptions インスタンスを作成する方法を示しています。1 つは対話型の要求向け、1 つはバックグラウンドの要求向けです。 次にこの例では、これら 2 つの再試行ポリシーをクライアントに対して設定して、それらのポリシーがすべての要求に適用されるようにします。さらに、対話型戦略を特定の要求に対して設定して、クライアントに適用された既定の設定をオーバーライドできるようにします。

using System;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Table;

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

        public async static Task Samples()
        {
            var storageAccount = CloudStorageAccount.Parse(connectionString);

            TableRequestOptions interactiveRequestOption = new TableRequestOptions()
            {
                RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(500), 3),
                // For Read-access geo-redundant storage, use PrimaryThenSecondary.
                // Otherwise set this to PrimaryOnly.
                LocationMode = LocationMode.PrimaryThenSecondary,
                // Maximum execution time based on the business use case.
                MaximumExecutionTime = TimeSpan.FromSeconds(2)
            };

            TableRequestOptions backgroundRequestOption = new TableRequestOptions()
            {
                // Client has a default exponential retry policy with 4 sec delay and 3 retry attempts
                // Retry delays will be approximately 3 sec, 7 sec, and 15 sec
                MaximumExecutionTime = TimeSpan.FromSeconds(30),
                // PrimaryThenSecondary in case of Read-access geo-redundant storage, else set this to PrimaryOnly
                LocationMode = LocationMode.PrimaryThenSecondary
            };

            var client = storageAccount.CreateCloudTableClient();
            // Client has a default exponential retry policy with 4 sec delay and 3 retry attempts
            // Retry delays will be approximately 3 sec, 7 sec, and 15 sec
            // ServerTimeout and MaximumExecutionTime are not set

            {
                // Set properties for the client (used on all requests unless overridden)
                // Different exponential policy parameters for background scenarios
                client.DefaultRequestOptions = backgroundRequestOption;
                // Linear policy for interactive scenarios
                client.DefaultRequestOptions = interactiveRequestOption;
            }

            {
                // set properties for a specific request
                var stats = await client.GetServiceStatsAsync(interactiveRequestOption, operationContext: null);
            }

            {
                // Set up notifications for an operation
                var context = new OperationContext();
                context.ClientRequestID = "some request id";
                context.Retrying += (sender, args) =>
                {
                    // Collect retry information
                };
                context.RequestCompleted += (sender, args) =>
                {
                    // Collect operation completion information
                };
                var stats = await client.GetServiceStatsAsync(null, context);
            }
        }
    }
}

詳細情報

一般的な 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 でも、再試行をログに記録できるよう、エラーを追跡する方法が提供されています。

詳細情報