Implémentation de la communication basée sur les événements entre les microservices (événements d’intégration)Implementing event-based communication between microservices (integration events)

Comme décrit précédemment, quand vous utilisez la communication basée sur les événements, un microservice publie un événement chaque fois qu’une chose notable se produit (par exemple, lorsqu’une entité commerciale est mise à jour).As described earlier, when you use event-based communication, a microservice publishes an event when something notable happens, such as when it updates a business entity. Les autres microservices s’abonnent à ces événements.Other microservices subscribe to those events. Lorsqu’un microservice reçoit un événement, il peut mettre à jour ses propres entités commerciales, ce qui peut générer la publication d’autres événements.When a microservice receives an event, it can update its own business entities, which might lead to more events being published. Il s’agit de l’essence même du concept de cohérence éventuelle.This is the essence of the eventual consistency concept. Ce système de publication/abonnement est généralement obtenu à l’aide de l’implémentation d’un bus d’événements.This publish/subscribe system is usually performed by using an implementation of an event bus. Le bus d’événements peut être conçu comme l’interface de l’API nécessaire pour s’abonner aux événements et s’en désabonner, ainsi que pour les publier.The event bus can be designed as an interface with the API needed to subscribe and unsubscribe to events and to publish events. Il peut également avoir une ou plusieurs implémentations basées sur une communication entre processus ou une communication de messagerie, telle qu’une file d’attente de messagerie ou un bus de service prenant en charge la communication asynchrone, ainsi qu’un modèle de publication/abonnement.It can also have one or more implementations based on any inter-process or messaging communication, such as a messaging queue or a service bus that supports asynchronous communication and a publish/subscribe model.

Vous pouvez utiliser des événements pour implémenter des transactions commerciales qui s’étendent sur plusieurs services, ce qui vous donne une cohérence éventuelle entre ces services.You can use events to implement business transactions that span multiple services, which give you eventual consistency between those services. Une transaction cohérente à terme se compose d’une série d’actions distribuées.An eventually consistent transaction consists of a series of distributed actions. À chaque action, le microservice met à jour une entité commerciale et publie un événement qui déclenche l’action suivante.At each action, the microservice updates a business entity and publishes an event that triggers the next action. La figure 6-18 ci-dessous montre un événement PriceUpdated publié par le biais d’un bus d’événements, ce qui signifie que la mise à jour du prix est propagée vers le panier et d’autres microservices.Figure 6-18 below, shows a PriceUpdated event published through an event bus, so the price update is propagated to the Basket and other microservices.

Diagramme de communication asynchrone pilotée par les événements avec un bus d’événements.

Figure 6-18.Figure 6-18. Communication pilotée par les événements et basée sur un bus d’événementsEvent-driven communication based on an event bus

Cette section explique comment implémenter ce type de communication avec .NET à l’aide d’une interface de bus d’événements générique, comme indiqué dans la figure 6-18.This section describes how you can implement this type of communication with .NET by using a generic event bus interface, as shown in Figure 6-18. Il existe plusieurs implémentations possibles, qui utilisent chacune leur propre technologie ou infrastructure, telles que RabbitMQ, Azure Service Bus ou tout autre Service Bus tiers open source ou commercial.There are multiple potential implementations, each using a different technology or infrastructure such as RabbitMQ, Azure Service Bus, or any other third-party open-source or commercial service bus.

Utilisation de répartiteurs de messages et de bus de services pour les systèmes de productionUsing message brokers and services buses for production systems

Comme indiqué dans la section relative à l’architecture, vous pouvez choisir parmi plusieurs technologies de messagerie pour l’implémentation de votre bus d’événements abstraits.As noted in the architecture section, you can choose from multiple messaging technologies for implementing your abstract event bus. Toutefois, ces technologies sont situées à des niveaux différents.But these technologies are at different levels. Par exemple, le répartiteur de messages RabbitMQ se trouve à un niveau inférieur à celui des produits commerciaux tels qu’Azure Service Bus, NServiceBus, MassTransit ou Brighter.For instance, RabbitMQ, a messaging broker transport, is at a lower level than commercial products like Azure Service Bus, NServiceBus, MassTransit, or Brighter. La plupart de ces produits peuvent fonctionner par-dessus RabbitMQ ou Azure Service Bus.Most of these products can work on top of either RabbitMQ or Azure Service Bus. Vous devez choisir le produit en fonction du nombre de fonctionnalités et du niveau de scalabilité prête à l’emploi dont vous avez besoin pour votre application.Your choice of product depends on how many features and how much out-of-the-box scalability you need for your application.

Si vous souhaitez uniquement implémenter une preuve de concept de bus d’événements pour votre environnement de développement, comme dans l’exemple eShopOnContainers, une simple implémentation par-dessus RabbitMQ exécutée dans un conteneur peut être suffisante.For implementing just an event bus proof-of-concept for your development environment, as in the eShopOnContainers sample, a simple implementation on top of RabbitMQ running as a container might be enough. Toutefois, pour les systèmes stratégiques et les systèmes de production qui nécessitent un haut niveau de scalabilité, il peut être utile d’évaluer et d’utiliser Azure Service Bus.But for mission-critical and production systems that need high scalability, you might want to evaluate and use Azure Service Bus.

Si vous avez besoin d’un haut niveau d’abstraction et de fonctionnalités plus riches telles que Sagas pour les processus longs qui facilitent le développement distribué, d’autres bus de services commerciaux et open source comme NServiceBus, MassTransit et Brighter méritent d’être évalués.If you require high-level abstractions and richer features like Sagas for long-running processes that make distributed development easier, other commercial and open-source service buses like NServiceBus, MassTransit, and Brighter are worth evaluating. Dans ce cas, les abstractions et l’API à utiliser sont généralement celles fournies par ces bus de services de haut niveau, et non vos propres abstractions (comme les abstractions de bus d’événements simples fournies dans eShopOnContainers).In this case, the abstractions and API to use would usually be directly the ones provided by those high-level service buses instead of your own abstractions (like the simple event bus abstractions provided at eShopOnContainers). Pour ce faire, vous pouvez rechercher les eShopOnContainers dupliqués à l’aide de NServiceBus (exemple dérivé supplémentaire implémenté par un logiciel particulier).For that matter, you can research the forked eShopOnContainers using NServiceBus (additional derived sample implemented by Particular Software).

Bien sûr, vous pourriez toujours créer vos propres fonctionnalités service bus sur des technologies de niveau inférieur telles que RabbitMQ et docker, mais le travail nécessaire pour « réinventer la roue » peut être trop coûteux pour une application d’entreprise personnalisée.Of course, you could always build your own service bus features on top of lower-level technologies like RabbitMQ and Docker, but the work needed to "reinvent the wheel" might be too costly for a custom enterprise application.

Pour réitérer : les exemples d’abstractions de bus d’événements et d’implémentation présentés dans l’exemple eShopOnContainers sont destinés à être utilisés uniquement comme preuve de concept.To reiterate: the sample event bus abstractions and implementation showcased in the eShopOnContainers sample are intended to be used only as a proof of concept. Une fois que vous avez décidé que vous souhaitez établir une communication asynchrone et pilotée par les événements, comme expliqué dans la section actuelle, vous devez choisir le produit Service Bus qui convient le mieux à vos besoins pour la production.Once you have decided that you want to have asynchronous and event-driven communication, as explained in the current section, you should choose the service bus product that best fits your needs for production.

Événements d’intégrationIntegration events

Les événements d’intégration sont utilisés pour synchroniser l’état du domaine sur plusieurs microservices ou systèmes externes.Integration events are used for bringing domain state in sync across multiple microservices or external systems. Cette fonctionnalité est effectuée en publiant des événements d’intégration en dehors du microservice.This functionality is done by publishing integration events outside the microservice. Lorsqu’un événement est publié sur plusieurs microservices récepteurs (sur tous les microservices abonnés à l’événement d’intégration), le gestionnaire d’événements de chaque microservice récepteur gère l’événement.When an event is published to multiple receiver microservices (to as many microservices as are subscribed to the integration event), the appropriate event handler in each receiver microservice handles the event.

Un événement d’intégration est essentiellement une classe conteneur de données, comme le montre l’exemple suivant :An integration event is basically a data-holding class, as in the following example:

public class ProductPriceChangedIntegrationEvent : IntegrationEvent
{
    public int ProductId { get; private set; }
    public decimal NewPrice { get; private set; }
    public decimal OldPrice { get; private set; }

    public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice,
        decimal oldPrice)
    {
        ProductId = productId;
        NewPrice = newPrice;
        OldPrice = oldPrice;
    }
}

Les événements d’intégration peuvent être définis au niveau de l’application de chaque microservice. De cette façon, ils sont dissociés des autres microservices, d’une manière comparable à la façon dont les ViewModels sont définis sur le serveur et sur le client.The integration events can be defined at the application level of each microservice, so they are decoupled from other microservices, in a way comparable to how ViewModels are defined in the server and client. Cependant, il n’est pas recommandé de partager une bibliothèque d’événements d’intégration entre plusieurs microservices, car cela aurait pour effet de coupler ces microservices avec une seule bibliothèque de données de définition d’événements.What is not recommended is sharing a common integration events library across multiple microservices; doing that would be coupling those microservices with a single event definition data library. Un tel partage est déconseillé, tout comme le partage d’un modèle de domaine entre plusieurs microservices, car les microservices doivent être complètement autonomes.You do not want to do that for the same reasons that you do not want to share a common domain model across multiple microservices: microservices must be completely autonomous.

Seules certaines bibliothèques peuvent être partagées entre plusieurs microservices.There are only a few kinds of libraries you should share across microservices. Parmi elles figurent les bibliothèques qui sont des blocs d’application finale, comme l’API cliente Event Bus de l’exemple eShopOnContainers.One is libraries that are final application blocks, like the Event Bus client API, as in eShopOnContainers. Vous avez également les bibliothèques qui constituent des outils pouvant être partagés en tant que composants NuGet, comme les sérialiseurs JSON.Another is libraries that constitute tools that could also be shared as NuGet components, like JSON serializers.

Le bus d’événementsThe event bus

Un bus d’événements permet une communication de type publication/abonnement entre les microservices, sans nécessiter que les composants soient explicitement informés de la présence des uns des autres, comme le montre la figure 6-19.An event bus allows publish/subscribe-style communication between microservices without requiring the components to explicitly be aware of each other, as shown in Figure 6-19.

Diagramme montrant le modèle de publication/d’abonnement de base.

Figure 6-19.Figure 6-19. Principes de base de la communication de type publication/abonnement avec un bus d’événementsPublish/subscribe basics with an event bus

Le diagramme ci-dessus montre que le microservice A effectue une publication sur le bus d’événements, qui distribue aux microservices B et C d’abonnement, sans que le serveur de publication doive connaître les abonnés.The above diagram shows that microservice A publishes to Event Bus, which distributes to subscribing microservices B and C, without the publisher needing to know the subscribers. Le bus d’événements est lié au modèle Observateur et au modèle Publication/Abonnement.The event bus is related to the Observer pattern and the publish-subscribe pattern.

Modèle ObservateurObserver pattern

Dans le modèle Observateur, votre objet principal (l’observable) envoie aux autres objets intéressés (les observateurs) des informations pertinentes (des événements).In the Observer pattern, your primary object (known as the Observable) notifies other interested objects (known as Observers) with relevant information (events).

Modèle Publication/AbonnementPublish/Subscribe (Pub/Sub) pattern

L’objectif du modèle Publication/Abonnement est le même que celui du modèle Observateur, c’est-à-dire que vous souhaitez informer les autres services de certains événements.The purpose of the Publish/Subscribe pattern is the same as the Observer pattern: you want to notify other services when certain events take place. Toutefois, il existe une différence importante entre ces deux modèles.But there is an important difference between the Observer and Pub/Sub patterns. Dans le modèle d’observateur, la diffusion est effectuée directement à partir de l’observable vers les observateurs, de sorte qu’ils se « identifient » les uns les autres.In the observer pattern, the broadcast is performed directly from the observable to the observers, so they "know" each other. Toutefois, lors de l’utilisation d’un modèle Pub/Sub, il existe un troisième composant, appelé Broker ou Broker de messages ou bus d’événements, qui est connu par le serveur de publication et l’abonné.But when using a Pub/Sub pattern, there is a third component, called broker, or message broker or event bus, which is known by both the publisher and subscriber. Par conséquent, lorsque vous utilisez le modèle Publication/Abonnement, celui qui publie et ses abonnés sont dissociés grâce au bus d’événements ou au répartiteur de messages.Therefore, when using the Pub/Sub pattern the publisher and the subscribers are precisely decoupled thanks to the mentioned event bus or message broker.

L’intermédiaire ou le bus d’événementsThe middleman or event bus

Comment permettre l’anonymat entre celui qui publie les événements et ses abonnés ?How do you achieve anonymity between publisher and subscriber? Un moyen simple consiste à laisser un intermédiaire s’occuper de toutes les communications.An easy way is let a middleman take care of all the communication. Un bus d’événements joue le rôle de cet intermédiaire.An event bus is one such middleman.

Un bus d’événements est généralement constitué de deux parties :An event bus is typically composed of two parts:

  • L’abstraction ou interfaceThe abstraction or interface.

  • Une ou plusieurs implémentationsOne or more implementations.

Dans la figure 6-19, vous pouvez voir que, du point de vue d’une application, le bus d’événements n’est autre qu’un canal de publication/abonnement.In Figure 6-19 you can see how, from an application point of view, the event bus is nothing more than a Pub/Sub channel. La façon dont vous implémentez cette communication asynchrone peut varier.The way you implement this asynchronous communication can vary. Plusieurs implémentations sont possibles, de sorte que vous pouvez passer de l’une à l’autre, selon les exigences de votre environnement (par exemple, s’il s’agit d’un environnement de production ou d’un environnement de développement).It can have multiple implementations so that you can swap between them, depending on the environment requirements (for example, production versus development environments).

Dans la figure 6-20, vous pouvez voir une abstraction d’un bus d’événements avec plusieurs implémentations basées sur des technologies de messagerie d’infrastructure telles que RabbitMQ, Azure Service Bus ou un autre répartiteur d’événements/messages.In Figure 6-20, you can see an abstraction of an event bus with multiple implementations based on infrastructure messaging technologies like RabbitMQ, Azure Service Bus, or another event/message broker.

Diagramme montrant l’ajout d’une couche d’abstraction de bus d’événements.

Figure 6-20.Figure 6- 20. Les différentes implémentations d’un bus d’événementsMultiple implementations of an event bus

Il est judicieux de définir le bus d’événements par le biais d’une interface, pour pouvoir l’implémenter avec plusieurs technologies comme RabbitMQ Azure Service Bus ou autre.It's good to have the event bus defined through an interface so it can be implemented with several technologies, like RabbitMQ Azure Service bus or others. Toutefois, comme mentionné précédemment, l’utilisation de vos propres abstractions (l’interface du bus d’événements) convient uniquement si vous avez besoin de fonctionnalités de bus d’événements de base, prises en charge par vos abstractions.However, and as mentioned previously, using your own abstractions (the event bus interface) is good only if you need basic event bus features supported by your abstractions. Si vous avez besoin de fonctionnalités de bus de services plus riches, utilisez l’API et les abstractions fournies par votre bus de services commercial préféré, plutôt que vos propres abstractions.If you need richer service bus features, you should probably use the API and abstractions provided by your preferred commercial service bus instead of your own abstractions.

Définition de l’interface d’un bus d’événementsDefining an event bus interface

Commençons par un code d’implémentation pour l’interface du bus d’événements et des implémentations possibles à des fins d’exploration.Let's start with some implementation code for the event bus interface and possible implementations for exploration purposes. L’interface doit être générique et simple, comme celle qui suit.The interface should be generic and straightforward, as in the following interface.

public interface IEventBus
{
    void Publish(IntegrationEvent @event);

    void Subscribe<T, TH>()
        where T : IntegrationEvent
        where TH : IIntegrationEventHandler<T>;

    void SubscribeDynamic<TH>(string eventName)
        where TH : IDynamicIntegrationEventHandler;

    void UnsubscribeDynamic<TH>(string eventName)
        where TH : IDynamicIntegrationEventHandler;

    void Unsubscribe<T, TH>()
        where TH : IIntegrationEventHandler<T>
        where T : IntegrationEvent;
}

La méthode Publish est simple.The Publish method is straightforward. Le bus d’événements va diffuser l’événement d’intégration qui lui a été passé à tous les microservices, et même aux applications externes, abonnées à cet événement.The event bus will broadcast the integration event passed to it to any microservice, or even an external application, subscribed to that event. Cette méthode est utilisée par le microservice qui publie l’événement.This method is used by the microservice that is publishing the event.

Les méthodes Subscribe (vous pouvez avoir plusieurs implémentations selon les arguments) sont utilisées par les microservices qui souhaitent recevoir des événements.The Subscribe methods (you can have several implementations depending on the arguments) are used by the microservices that want to receive events. Cette méthode a deux arguments.This method has two arguments. Le premier est l’événement d’intégration auquel s’abonner (IntegrationEvent).The first is the integration event to subscribe to (IntegrationEvent). Le deuxième argument est le gestionnaire d’événements d’intégration (ou méthode de rappel) nommé IIntegrationEventHandler<T>, qui doit être exécuté lorsque le microservice récepteur obtient le message d’événement d’intégration.The second argument is the integration event handler (or callback method), named IIntegrationEventHandler<T>, to be executed when the receiver microservice gets that integration event message.

Ressources supplémentairesAdditional resources

Certaines solutions de messagerie prêtes pour la production :Some production-ready messaging solutions: