Azure Event Grid でのクライアント側フェールオーバー実装

ディザスター リカバリーには、通常、リージョンが異常になったときの中断を防ぐためのバックアップ リソースの作成が含まれます。 このプロセス中は、ワークロードに Azure Event Grid リソースのプライマリとセカンダリのリージョンが必要になります。

アプリケーション機能の重大な損失から復旧するには、さまざまな方法があります。 この記事では、異常なリソースまたはリージョンによる障害から復旧するためのクライアントの準備で従う必要があるチェックリストについて説明します。

Event Grid は、サーバー側で手動と自動の geo ディザスター リカバリー (GeoDR) をサポートしています。 フェールオーバー プロセスをさらに細かく制御したい場合には、クライアント側のディザスター リカバリー ロジックを実装することもできます。 自動 GeoDR の詳細については、「Server-side geo disaster recovery in Azure Event Grid (Azure Event Grid 内のサーバー側 geo ディザスター リカバリー)」を参照してください。

Event Grid でのクライアント側フェールオーバーと geo ディザスター リカバリーのサポートを次の表に示します。

Event Grid リソース クライアント側フェールオーバーのサポート geo ディザスター リカバリー (GeoDR) のサポート
カスタム トピック サポートされています 地域をまたがる/地域内
システム トピック サポートされていません 自動的に有効化
ドメイン サポートされています 地域をまたがる/地域内
パートナー名前空間 サポートされています サポートされていません
名前空間 サポートされています サポートされていません

クライアント側のフェールオーバーに関する考慮事項

  1. プライマリ Event Grid リソースを作成して構成します。
  2. セカンダリ Event Grid リソースを作成して構成します。
  3. 両方のリソースで同じ構成、サブリソース、機能が有効になっている必要があることに注意してください。
  4. Event Grid リソースは、異なるリージョンでホストされている必要があります。
  5. Event Grid リソースに配信不能のストレージ リソースなどの依存リソースがある場合は、使用されているのと同じリージョンをセカンダリ Event Grid リソースで使用する必要があります。
  6. 復旧計画リソースが適切に機能していることを保証するために、エンドポイントが定期的にテストされるようにしてください。

カスタム トピックの基本的なクライアント側フェールオーバー実装サンプル

次のサンプル コードは、最初にプライマリ トピックへのパブリッシュを試行するシンプルな .NET パブリッシャーです。 成功しなかった場合は、セカンダリ トピックにフェールオーバーします。 どちらの場合でも、https://<topic-name>.<topic-region>.eventgrid.azure.net/api/health に対して GET を実行することで、他のトピックの正常性 API がチェックされます。 正常なトピックは、 /api/health エンドポイントに対して GET が実行された場合に常に 200 OK で応答します。

Note

次のサンプル コードは、デモンストレーションのみを目的としており、運用環境での使用を目的としていません。

using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure;
using Azure.Messaging.EventGrid;

namespace EventGridFailoverPublisher
{
    // This captures the "Data" portion of an EventGridEvent on a custom topic
    class FailoverEventData
    {
        public string TestStatus { get; set; }
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            // TODO: Enter the endpoint each topic. You can find this topic endpoint value
            // in the "Overview" section in the "Event Grid topics" page in Azure Portal..
            string primaryTopic = "https://<primary-topic-name>.<primary-topic-region>.eventgrid.azure.net/api/events";
            string secondaryTopic = "https://<secondary-topic-name>.<secondary-topic-region>.eventgrid.azure.net/api/events";

            // TODO: Enter topic key for each topic. You can find this in the "Access Keys" section in the
            // "Event Grid topics" page in Azure Portal.
            string primaryTopicKey = "<your-primary-topic-key>";
            string secondaryTopicKey = "<your-secondary-topic-key>";

            Uri primaryTopicUri = new Uri(primaryTopic);
            Uri secondaryTopicUri = new Uri(secondaryTopic);

            Uri primaryTopicHealthProbe = new Uri($"https://{primaryTopicUri.Host}/api/health");
            Uri secondaryTopicHealthProbe = new Uri($"https://{secondaryTopicUri.Host}/api/health");

            var httpClient = new HttpClient();

            try
            {
                var client = new EventGridPublisherClient(primaryTopicUri, new AzureKeyCredential(primaryTopicKey));

                await client.SendEventsAsync(GetEventsList());
                Console.Write("Published events to primary Event Grid topic.");

                HttpResponseMessage health = httpClient.GetAsync(secondaryTopicHealthProbe).Result;
                Console.Write("\n\nSecondary Topic health " + health);
            }
            catch (RequestFailedException ex)
            {
                var client = new EventGridPublisherClient(secondaryTopicUri, new AzureKeyCredential(secondaryTopicKey));

                await client.SendEventsAsync(GetEventsList());
                Console.Write("Published events to secondary Event Grid topic. Reason for primary topic failure:\n\n" + ex);

                HttpResponseMessage health = await httpClient.GetAsync(primaryTopicHealthProbe);
                Console.WriteLine($"Primary Topic health {health}");
            }

            Console.ReadLine();
        }

        static IList<EventGridEvent> GetEventsList()
        {
            List<EventGridEvent> eventsList = new List<EventGridEvent>();

            for (int i = 0; i < 5; i++)
            {
                eventsList.Add(new EventGridEvent(
                    subject: "test" + i,
                    eventType: "Contoso.Failover.Test",
                    dataVersion: "2.0",
                    data: new FailoverEventData
                    {
                        TestStatus = "success"
                    }));
            }

            return eventsList;
        }
    }
}

試してみる

お客様のコンポーネントをすべて正しく用意できたところで、お客様のフェールオーバー実装をテストできます。

フェールオーバーが機能することを確認するために、プライマリ トピックのキーの文字をいくつか変更して、それを無効にできます。 イベント発行元の実行をもう一度試してみます。 次のサンプル イベントは引き続き Event Grid を通過しますが、クライアントを確認すると、セカンダリ トピック経由で発行されていることがわかります。

拡張の可能性

お客様のニーズに基づいてこのサンプルを拡張する方法は多数あります。 高負荷のシナリオでは、定期的にトピックの正常性 API を個別にチェックするとよいでしょう。 そうすることで、もしトピックがダウンしても、発行するたびにそれをチェックする必要がなくなります。 トピックが正常でないことがわかったら、セカンダリ トピックへの発行を既定にすることができます。

同様に、お客様の特定のニーズに基づいてフェールバック ロジックを実装するとよいでしょう。 最も近いデータ センターに発行することが、待ち時間を短縮するうえで非常に重要である場合、フェールオーバーしたトピックの正常性 API を定期的にプローブできます。 正常な状態に戻ったら、より近いデータ センターにフェールバックしても問題ありません。

次のステップ