Implementera en händelsebuss med RabbitMQ för utvecklings- eller testmiljön
Dricks
Det här innehållet är ett utdrag från eBook, .NET Microservices Architecture for Containerized .NET Applications, tillgängligt på .NET Docs eller som en kostnadsfri nedladdningsbar PDF som kan läsas offline.
Vi bör börja med att säga att om du skapar din anpassade händelsebuss baserat på RabbitMQ som körs i en container, som eShopOnContainers-programmet gör, bör den endast användas för dina utvecklings- och testmiljöer. Använd den inte för produktionsmiljön, såvida du inte skapar den som en del av en produktionsklar servicebuss enligt beskrivningen i avsnittet Ytterligare resurser nedan. En enkel anpassad händelsebuss kanske saknar många produktionsklara kritiska funktioner som en kommersiell servicebuss har.
En av de anpassade implementeringarna av event bus i eShopOnContainers är i princip ett bibliotek som använder RabbitMQ-API:et. (Det finns en annan implementering baserad på Azure Service Bus.)
Med event bus-implementeringen med RabbitMQ kan mikrotjänster prenumerera på händelser, publicera händelser och ta emot händelser, enligt bild 6–21.
Bild 6-21. RabbitMQ-implementering av en händelsebuss
RabbitMQ fungerar som mellanhand mellan meddelandeutgivare och prenumeranter för att hantera distribution. I koden implementerar klassen EventBusRabbitMQ det generiska IEventBus-gränssnittet. Den här implementeringen baseras på beroendeinmatning så att du kan växla från den här utvecklings-/testversionen till en produktionsversion.
public class EventBusRabbitMQ : IEventBus, IDisposable
{
// Implementation using RabbitMQ API
//...
}
RabbitMQ-implementeringen av en exempel-dev/test-händelsebuss är exempelkod. Den måste hantera anslutningen till RabbitMQ-servern och ange kod för att publicera en meddelandehändelse till köerna. Den måste också implementera en ordlista med samlingar med integrationshändelsehanterare för varje händelsetyp. dessa händelsetyper kan ha olika instansiering och olika prenumerationer för varje mottagarmikrotjänst, enligt bild 6–21.
Implementera en enkel publiceringsmetod med RabbitMQ
Följande kod är en förenklad version av en händelsebussimplementering för RabbitMQ för att visa hela scenariot. Du hanterar inte anslutningen på det här sättet. Om du vill se den fullständiga implementeringen läser du den faktiska koden i lagringsplatsen 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);
}
}
}
Den faktiska koden för metoden Publish i eShopOnContainers-programmet förbättras med hjälp av en återförsöksprincip för Polly , som försöker utföra uppgiften igen några gånger om RabbitMQ-containern inte är klar. Det här scenariot kan inträffa när docker-compose startar containrarna. Till exempel kan RabbitMQ-containern starta långsammare än de andra containrarna.
Som tidigare nämnts finns det många möjliga konfigurationer i RabbitMQ, så den här koden bör endast användas för utvecklings-/testmiljöer.
Implementera prenumerationskoden med RabbitMQ-API:et
Precis som med publiceringskoden är följande kod en förenkling av en del av händelsebussimplementeringen för RabbitMQ. Återigen behöver du vanligtvis inte ändra det om du inte förbättrar det.
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>();
}
}
Varje händelsetyp har en relaterad kanal för att hämta händelser från RabbitMQ. Du kan sedan ha så många händelsehanterare per kanal och händelsetyp som behövs.
Metoden Prenumerera accepterar ett IIntegrationEventHandler-objekt, som är som en motringningsmetod i den aktuella mikrotjänsten, plus dess relaterade IntegrationEvent-objekt. Koden lägger sedan till händelsehanteraren i listan över händelsehanterare som varje integreringshändelsetyp kan ha per klientmikrotjänst. Om klientkoden inte redan har prenumererat på händelsen skapar koden en kanal för händelsetypen så att den kan ta emot händelser i push-format från RabbitMQ när händelsen publiceras från någon annan tjänst.
Som nämnts ovan har händelsebussen som implementerats i eShopOnContainers endast ett utbildningssyfte, eftersom den bara hanterar huvudscenarierna, så den är inte redo för produktion.
För produktionsscenarier kontrollerar du de ytterligare resurserna nedan, som är specifika för RabbitMQ, och avsnittet Implementera händelsebaserad kommunikation mellan mikrotjänster .
Ytterligare resurser
En produktionsklar lösning med stöd för RabbitMQ.
Peregrine Anslut – Förenkla integreringen med effektiv design, distribution och hantering av appar, API:er och arbetsflöden
https://www.peregrineconnect.com/why-peregrine/rabbitmq-integrationNServiceBus – Fullständigt stödd kommersiell servicebuss med avancerade hanterings- och övervakningsverktyg för .NET
https://particular.net/EasyNetQ – .NET API-klient med öppen källkod för RabbitMQ
https://easynetq.com/MassTransit – kostnadsfrit distribuerat programramverk med öppen källkod för .NET
https://masstransit-project.com/Rebus – .NET Service Bus med öppen källkod
https://github.com/rebus-org/Rebus