Delen via


Een gebeurtenisbus implementeren met RabbitMQ voor de ontwikkel- of testomgeving

Tip

Deze inhoud is een fragment uit het eBook, .NET Microservices Architecture for Containerized .NET Applications, beschikbaar op .NET Docs of als een gratis downloadbare PDF die offline kan worden gelezen.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

We moeten beginnen met het zeggen dat als u uw aangepaste gebeurtenisbus maakt op basis van RabbitMQ die wordt uitgevoerd in een container, zoals de eShopOnContainers-toepassing doet, deze alleen moet worden gebruikt voor uw ontwikkel- en testomgevingen. Gebruik deze niet voor uw productieomgeving, tenzij u deze bouwt als onderdeel van een servicebus die gereed is voor productie, zoals beschreven in de sectie Aanvullende resources hieronder. Een eenvoudige aangepaste gebeurtenisbus mist mogelijk veel essentiële functies die gereed zijn voor productie die een commerciële servicebus heeft.

Een van de aangepaste implementaties van event bus in eShopOnContainers is in feite een bibliotheek met behulp van de RabbitMQ-API. (Er is nog een implementatie op basis van Azure Service Bus.)

Met de implementatie van event bus met RabbitMQ kunnen microservices zich abonneren op gebeurtenissen, gebeurtenissen publiceren en gebeurtenissen ontvangen, zoals wordt weergegeven in afbeelding 6-21.

Diagram met RabbitMQ tussen de afzender van het bericht en de ontvanger van het bericht.

Afbeelding 6-21. RabbitMQ-implementatie van een gebeurtenisbus

RabbitMQ fungeert als intermediair tussen berichtuitgever en abonnees om distributie te verwerken. In de code implementeert de EventBusRabbitMQ-klasse de algemene IEventBus-interface. Deze implementatie is gebaseerd op afhankelijkheidsinjectie, zodat u kunt wisselen van deze dev/test-versie naar een productieversie.

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

De RabbitMQ-implementatie van een voorbeeld van een dev/test event bus is standaardcode. Het moet de verbinding met de RabbitMQ-server afhandelen en code opgeven voor het publiceren van een berichtgebeurtenis in de wachtrijen. Het moet ook een woordenlijst met verzamelingen integratiegebeurtenissen-handlers implementeren voor elk gebeurtenistype; deze gebeurtenistypen kunnen een andere instantie en verschillende abonnementen hebben voor elke ontvangermicroservice, zoals wordt weergegeven in afbeelding 6-21.

Een eenvoudige publicatiemethode implementeren met RabbitMQ

De volgende code is een vereenvoudigde versie van een event bus-implementatie voor RabbitMQ om het hele scenario te laten zien. Je verwerkt de verbinding niet echt op deze manier. Zie de werkelijke code in de dotnet-architecture/eShopOnContainers-opslagplaats voor de volledige implementatie.

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

De werkelijke code van de methode Publish in de toepassing eShopOnContainers wordt verbeterd met behulp van een beleid voor opnieuw proberen van Polly , waarmee de taak een aantal keren opnieuw wordt uitgevoerd als de RabbitMQ-container niet gereed is. Dit scenario kan optreden wanneer docker-compose de containers start; De RabbitMQ-container kan bijvoorbeeld langzamer beginnen dan de andere containers.

Zoals eerder vermeld, zijn er veel mogelijke configuraties in RabbitMQ, dus deze code moet alleen worden gebruikt voor ontwikkel-/testomgevingen.

De abonnementscode implementeren met de RabbitMQ-API

Net als bij de publicatiecode is de volgende code een vereenvoudiging van een deel van de event bus-implementatie voor RabbitMQ. Nogmaals, u hoeft het meestal niet te wijzigen, tenzij u het verbetert.

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

Elk gebeurtenistype heeft een gerelateerd kanaal om gebeurtenissen op te halen van RabbitMQ. U kunt vervolgens zoveel gebeurtenis-handlers per kanaal en gebeurtenistype hebben als nodig is.

De methode Subscribe accepteert een IIntegrationEventHandler-object, dat vergelijkbaar is met een callback-methode in de huidige microservice, plus het bijbehorende IntegrationEvent-object. De code voegt die gebeurtenis-handler vervolgens toe aan de lijst met gebeurtenis-handlers die elk type integratie-gebeurtenis per clientmicroservice kunnen hebben. Als de clientcode nog niet is geabonneerd op de gebeurtenis, maakt de code een kanaal voor het gebeurtenistype, zodat deze gebeurtenissen kan ontvangen in een pushstijl van RabbitMQ wanneer deze gebeurtenis wordt gepubliceerd vanuit een andere service.

Zoals hierboven vermeld, heeft de gebeurtenisbus die is geïmplementeerd in eShopOnContainers slechts een educatief doel, omdat deze alleen de hoofdscenario's afhandelt, dus het is niet gereed voor productie.

Voor productiescenario's controleert u de aanvullende resources hieronder, specifiek voor RabbitMQ en de sectie Op gebeurtenissen gebaseerde communicatie implementeren tussen microservices .

Aanvullende bronnen

Een oplossing die gereed is voor productie met ondersteuning voor RabbitMQ.