Udostępnij za pośrednictwem


Implementowanie magistrali zdarzeń z oprogramowaniem RabbitMQ na potrzeby środowisk testowych lub deweloperskich

Napiwek

Ta zawartość jest fragmentem książki eBook, architektury mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET dostępnych na platformie .NET Docs lub jako bezpłatnego pliku PDF, który można odczytać w trybie offline.

Architektura mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET — miniatura książki eBook.

Zacznijmy od stwierdzenia, że jeśli tworzysz niestandardową magistralę zdarzeń opartą na środowisku RabbitMQ uruchomionym w kontenerze, tak jak robi to aplikacja eShopOnContainers, powinna być używana tylko dla środowisk programistycznych i testowych. Nie używaj go w środowisku produkcyjnym, chyba że tworzysz go jako część produkcyjnej magistrali usług zgodnie z opisem w sekcji Dodatkowe zasoby poniżej. Prosta niestandardowa magistrala zdarzeń może nie mieć wielu krytycznych funkcji gotowych do produkcji, które ma komercyjna magistrala usług.

Jedną z niestandardowych implementacji magistrali zdarzeń w eShopOnContainers jest w zasadzie biblioteka korzystająca z interfejsu API RabbitMQ. (Istnieje inna implementacja oparta na usłudze Azure Service Bus).

Implementacja magistrali zdarzeń za pomocą programu RabbitMQ umożliwia mikrousługi subskrybowanie zdarzeń, publikowanie zdarzeń i odbieranie zdarzeń, jak pokazano na rysunku 6–21.

Diagram przedstawiający usługę RabbitMQ między nadawcą komunikatów i odbiornikiem komunikatów.

Rysunek 6–21. Implementacja rozwiązania RabbitMQ magistrali zdarzeń

RabbitMQ działa jako pośrednik między wydawcą i subskrybentami komunikatów w celu obsługi dystrybucji. W kodzie klasa EventBusRabbitMQ implementuje ogólny interfejs IEventBus. Ta implementacja jest oparta na iniekcji zależności, dzięki czemu można zamienić tę wersję dewelopera/testową na wersję produkcyjną.

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

Implementacja RabbitMQ przykładowej magistrali zdarzeń tworzenia i testowania jest standardowy kod. Musi obsługiwać połączenie z serwerem RabbitMQ i dostarczać kod do publikowania zdarzenia komunikatu w kolejkach. Musi również zaimplementować słownik kolekcji programów obsługi zdarzeń integracji dla każdego typu zdarzenia; te typy zdarzeń mogą mieć różne wystąpienia i różne subskrypcje dla każdej mikrousługi odbiorcy, jak pokazano na rysunku 6-21.

Implementowanie prostej metody publikowania za pomocą programu RabbitMQ

Poniższy kod jest uproszczoną wersją implementacji magistrali zdarzeń dla RabbitMQ, aby zaprezentować cały scenariusz. Tak naprawdę nie obsługujesz połączenia w ten sposób. Aby wyświetlić pełną implementację, zobacz rzeczywisty kod w repozytorium 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);
       }
    }
}

Rzeczywisty kod metody Publish w aplikacji eShopOnContainers został ulepszony przy użyciu zasad ponawiania ponawiania polly , które ponawia próbę zadania kilka razy w przypadku, gdy kontener RabbitMQ nie jest gotowy. Ten scenariusz może wystąpić, gdy program Docker-compose uruchamia kontenery; na przykład kontener RabbitMQ może zaczynać się wolniej niż inne kontenery.

Jak wspomniano wcześniej, istnieje wiele możliwych konfiguracji w rabbitMQ, więc ten kod powinien być używany tylko dla środowisk deweloperskich/testowych.

Implementowanie kodu subskrypcji za pomocą interfejsu API RabbitMQ

Podobnie jak w przypadku kodu publikowania, poniższy kod jest uproszczeniem części implementacji magistrali zdarzeń dla RabbitMQ. Ponownie, zwykle nie trzeba go zmieniać, chyba że go ulepszasz.

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

Każdy typ zdarzenia ma powiązany kanał do pobierania zdarzeń z RabbitMQ. Następnie można mieć dowolną liczbę procedur obsługi zdarzeń na kanał i typ zdarzenia zgodnie z potrzebami.

Metoda Subscribe akceptuje obiekt IIntegrationEventHandler, który jest jak metoda wywołania zwrotnego w bieżącej mikrousłudze oraz powiązany obiekt IntegrationEvent. Następnie kod dodaje program obsługi zdarzeń do listy programów obsługi zdarzeń, które mogą mieć każdy typ zdarzenia integracji dla mikrousługi klienta. Jeśli kod klienta nie został jeszcze zasubskrybowany do zdarzenia, kod tworzy kanał dla typu zdarzenia, aby mógł odbierać zdarzenia w stylu wypychania z rabbitMQ, gdy to zdarzenie jest publikowane z dowolnej innej usługi.

Jak wspomniano powyżej, magistrala zdarzeń zaimplementowana w eShopOnContainers ma tylko cel edukacyjny, ponieważ obsługuje tylko główne scenariusze, więc nie jest gotowy do produkcji.

W przypadku scenariuszy produkcyjnych zapoznaj się z poniższymi dodatkowymi zasobami, specyficznymi dla środowiska RabbitMQ i sekcją Implementowanie komunikacji opartej na zdarzeniach między mikrousługami .

Dodatkowe zasoby

Gotowe do produkcji rozwiązanie z obsługą oprogramowania RabbitMQ.