次の方法で共有


開発またはテスト環境用の RabbitMQ を使用したイベント バスの実装

ヒント

このコンテンツは、.NET Docs で入手できる、またはオフラインで読み取ることができる無料のダウンロード可能な PDF として入手できる、コンテナー化された .NET アプリケーションの電子ブックである .NET マイクロサービス アーキテクチャからの抜粋です。

コンテナー化された .NET アプリケーションの .NET マイクロサービス アーキテクチャの電子ブックの表紙サムネイル。

まず、コンテナーで実行されている RabbitMQ に基づいてカスタム イベント バスを作成する場合は、eShopOnContainers アプリケーションと同様に、開発環境とテスト環境にのみ使用する必要があります。 以下の「 その他のリソース」セクションの説明に従って、運用環境対応のサービス バスの一部として構築する場合を除き、運用環境には使用しないでください。 単純なカスタム イベント バスには、商用サービス バスに含まれる多くの運用対応の重要な機能が不足している可能性があります。

eShopOnContainers のイベント バス カスタム実装の 1 つは、基本的に RabbitMQ API を使用するライブラリです。 (Azure Service Bus に基づく別の実装があります)。

RabbitMQ を使用したイベント バスの実装では、図 6-21 に示すように、マイクロサービスはイベントのサブスクライブ、イベントの発行、イベントの受信を行うことができます。

メッセージ送信者とメッセージ受信者の間の RabbitMQ を示す図。

図 6-21 イベント バスの RabbitMQ 実装

RabbitMQ は、配信を処理するために、メッセージ発行元とサブスクライバーの間の仲介役として機能します。 このコードでは、EventBusRabbitMQ クラスは汎用 IEventBus インターフェイスを実装します。 この実装は依存関係の挿入に基づいているため、この開発/テスト バージョンから実稼働バージョンにスワップできます。

public class EventBusRabbitMQ : IEventBus, IDisposable
{
    // Implementation using RabbitMQ API
    //...
}

サンプル開発/テスト イベント バスの RabbitMQ 実装は定型コードです。 RabbitMQ サーバーへの接続を処理し、メッセージ イベントをキューに発行するためのコードを提供する必要があります。 また、イベントの種類ごとに統合イベント ハンドラーのコレクションのディクショナリを実装する必要があります。これらのイベントの種類は、図 6-21 に示すように、受信側マイクロサービスごとに異なるインスタンス化と異なるサブスクリプションを持つことができます。

RabbitMQ を使用した単純な発行メソッドの実装

次のコードは、RabbitMQ のイベント バス実装の 簡略化された バージョンであり、シナリオ全体を示しています。 実際にこの方法で接続を処理することはありません。 完全な実装を確認するには、 dotnet-architecture/eShopOnContainers リポジトリの実際のコードを参照してください。

public class EventBusRabbitMQ : IEventBus, IDisposable
{
    // Member objects and other methods ...
    // ...

    public void Publish(IntegrationEvent @event)
    {
        var eventName = @event.GetType().Name;
        var factory = new ConnectionFactory() { HostName = _connectionString };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: _brokerName,
                type: "direct");
            string message = JsonConvert.SerializeObject(@event);
            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: _brokerName,
                routingKey: eventName,
                basicProperties: null,
                body: body);
       }
    }
}

eShopOnContainers アプリケーションの Publish メソッドの 実際のコード は、RabbitMQ コンテナーの準備ができていない場合にタスクを再試行する Polly 再試行ポリシーを使用して改善されています。 このシナリオは、docker-compose がコンテナーを開始するときに発生する可能性があります。たとえば、RabbitMQ コンテナーの起動速度が他のコンテナーよりも遅くなる場合があります。

前述のように、RabbitMQ には多くの構成が考えられるため、このコードは開発/テスト環境でのみ使用する必要があります。

RabbitMQ API を使用したサブスクリプション コードの実装

発行コードと同様に、次のコードは RabbitMQ のイベント バス実装の一部を簡略化したものです。 ここでも、改善しない限り、通常は変更する必要はありません。

public class EventBusRabbitMQ : IEventBus, IDisposable
{
    // Member objects and other methods ...
    // ...

    public void Subscribe<T, TH>()
        where T : IntegrationEvent
        where TH : IIntegrationEventHandler<T>
    {
        var eventName = _subsManager.GetEventKey<T>();

        var containsKey = _subsManager.HasSubscriptionsForEvent(eventName);
        if (!containsKey)
        {
            if (!_persistentConnection.IsConnected)
            {
                _persistentConnection.TryConnect();
            }

            using (var channel = _persistentConnection.CreateModel())
            {
                channel.QueueBind(queue: _queueName,
                                    exchange: BROKER_NAME,
                                    routingKey: eventName);
            }
        }

        _subsManager.AddSubscription<T, TH>();
    }
}

各イベントの種類には、RabbitMQ からイベントを取得するための関連チャネルがあります。 その後、チャネルとイベントの種類ごとに必要な数のイベント ハンドラーを持つことができます。

Subscribe メソッドは、現在のマイクロサービスのコールバック メソッドに似た IIntegrationEventHandler オブジェクトと、関連する IntegrationEvent オブジェクトを受け取ります。 その後、コードは、各統合イベントの種類がクライアント マイクロサービスごとに持つイベント ハンドラーの一覧にそのイベント ハンドラーを追加します。 クライアント コードがまだイベントにサブスクライブされていない場合、コードはイベントの種類のチャネルを作成し、そのイベントが他のサービスから発行されたときに RabbitMQ からプッシュ スタイルでイベントを受信できるようにします。

前述のように、eShopOnContainers で実装されるイベント バスは、主なシナリオのみを処理するため、運用環境の準備ができていないため、教育目的しかありません。

運用環境のシナリオでは、RabbitMQ に固有の以下の追加リソースと、 マイクロサービス間のイベントベースの通信の実装に関する セクションを確認してください。

その他のリソース

RabbitMQ をサポートする運用対応ソリューション。