Freigeben über


Implementieren eines Veranstaltungsbus mit RabbitMQ für die Entwicklungs- oder Testumgebung

Tipp

Dieser Inhalt ist ein Auszug aus dem eBook .NET Microservices Architecture for Containerized .NET Applications, verfügbar auf .NET Docs oder als kostenlose herunterladbare PDF, die offline gelesen werden kann.

.NET Microservices-Architektur für containerisierte .NET-Anwendungen eBook-Cover-Thumbnail.

Wenn Sie den benutzerdefinierten Ereignisbus basierend auf in einem Container ausgeführten RabbitMQ erstellen, so wie bei der Anwendung eShopOnContainers, sollte er nur in Entwicklungs- und Testumgebungen verwendet werden. Verwenden Sie sie nicht für Ihre Produktionsumgebung, es sei denn, Sie erstellen sie als Teil eines produktionsbereiten Servicebus, wie im Abschnitt "Zusätzliche Ressourcen" weiter unten beschrieben. Ein einfacher benutzerdefinierter Ereignisbus fehlt möglicherweise viele produktionsbereite kritische Funktionen, die ein kommerzieller Servicebus hat.

Eine der benutzerdefinierten Ereignisbusimplementierungen in eShopOnContainers ist im Grunde eine Bibliothek mit der RabbitMQ-API. (Es gibt eine weitere Implementierung, die auf Azure Service Bus basiert.)

Mit der Implementierung des Ereignisbus mit RabbitMQ können Microservices Ereignisse abonnieren, Ereignisse veröffentlichen und Ereignisse empfangen, wie in Abbildung 6-21 dargestellt.

Diagramm mit RabbitMQ zwischen Nachrichtensender und Nachrichtenempfänger.

Abbildung 6-21. RabbitMQ-Implementierung eines Ereignisbusses

RabbitMQ fungiert als Vermittler zwischen Nachrichtenherausgeber und Abonnenten, um die Verteilung zu verarbeiten. Im Code implementiert die EventBusRabbitMQ-Klasse die generische IEventBus-Schnittstelle. Diese Implementierung basiert auf Dependency Injection, sodass Sie von dieser Entwicklungs-/Testversion in eine Produktionsversion wechseln können.

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

Die RabbitMQ-Implementierung eines Beispiel-Entwicklungs- und Test-Ereignisbusses ist Standardcode. Es muss die Verbindung mit dem RabbitMQ-Server verarbeiten und Code zum Veröffentlichen eines Nachrichtenereignisses in die Warteschlangen bereitstellen. Außerdem muss ein Wörterbuch mit Auflistungen von Integrationsereignishandlern für jeden Ereignistyp implementiert werden. Diese Ereignistypen können eine andere Instanziierung und unterschiedliche Abonnements für jeden Empfänger-Microservice aufweisen, wie in Abbildung 6-21 dargestellt.

Implementieren einer einfachen Veröffentlichungsmethode mit RabbitMQ

Der folgende Code ist eine vereinfachte Version einer Ereignisbusimplementierung für RabbitMQ, um das gesamte Szenario zu präsentieren. Die Verbindung wird nicht wirklich so hergestellt. Im Repository dotnet-architecture/eShopOnContainers finden Sie den tatsächlichen Code zur vollständigen Implementierung.

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);
       }
    }
}

Der tatsächliche Code der Publish-Methode in der eShopOnContainers-Anwendung wird mithilfe einer Polly-Wiederholungsrichtlinie verbessert, die die Aufgabe einige Male wiederholt, falls der RabbitMQ-Container nicht bereit ist. Dieses Szenario kann auftreten, wenn docker-compose die Container startet; Beispielsweise kann der RabbitMQ-Container langsamer beginnen als die anderen Container.

Wie bereits erwähnt, gibt es viele mögliche Konfigurationen in RabbitMQ, sodass dieser Code nur für Entwicklungs-/Testumgebungen verwendet werden sollte.

Implementieren des Abonnementcodes mit der RabbitMQ-API

Wie beim Veröffentlichungscode ist der folgende Code eine Vereinfachung des Teils der Ereignisbusimplementierung für RabbitMQ. Wie gesagt müssen Sie ihn normalerweise nicht ändern, es sei denn, Sie nehmen Verbesserungen vor.

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>();
    }
}

Jeder Ereignistyp verfügt über einen zugehörigen Kanal, um Ereignisse von RabbitMQ abzurufen. Sie können dann beliebig viele Ereignishandler pro Kanal und Ereignistyp verwenden.

Die Subscribe-Methode akzeptiert ein IIntegrationEventHandler-Objekt, das wie eine Rückrufmethode im aktuellen Microservice sowie das zugehörige IntegrationEvent-Objekt ist. Der Code fügt dann diesen Ereignishandler der Liste der Ereignishandler hinzu, über die jeder Integrationsereignistyp pro Client-Microservice verfügen kann. Wenn der Clientcode noch nicht auf das Ereignis abonniert ist, erstellt der Code einen Kanal für den Ereignistyp, damit er Ereignisse im Push-Stil von RabbitMQ empfangen kann, sobald dieses Ereignis von einem anderen Dienst veröffentlicht wird.

Wie bereits erwähnt, hat der in eShopOnContainers implementierte Ereignisbus nur einen Bildungszweck, da er nur die hauptszenarien behandelt, sodass er nicht für die Produktion bereit ist.

Für Produktionsszenarien überprüfen Sie die unten aufgeführten zusätzlichen Ressourcen speziell für RabbitMQ und den Abschnitt "Implementieren der ereignisbasierten Kommunikation zwischen Microservices ".

Weitere Ressourcen

Eine produktionsfähige Lösung mit Unterstützung für RabbitMQ.