Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Conseil / Astuce
Ce contenu est un extrait du livre électronique 'Architecture des microservices .NET pour les applications .NET conteneurisées', disponible sur .NET Docs ou en tant que PDF téléchargeable gratuitement, lisible hors ligne.
Comme décrit précédemment, lorsque vous utilisez la communication basée sur des événements, un microservice publie un événement lorsqu’un événement notable se produit, par exemple lorsqu’il met à jour une entité métier. D’autres microservices s’abonnent à ces événements. Lorsqu’un microservice reçoit un événement, il peut mettre à jour ses propres entités métier, ce qui peut entraîner la publication d’événements supplémentaires. C’est l’essence du concept de cohérence éventuel. Ce système de publication/abonnement est généralement effectué à l’aide d’une implémentation d’un bus d’événements. Le bus d’événements peut être conçu comme une interface avec l’API nécessaire pour s’abonner et se désabonner des événements et publier des événements. Il peut également avoir une ou plusieurs implémentations basées sur n’importe quelle communication interprocessus ou de messagerie, telle qu’une file d’attente de messagerie ou un service bus qui prend en charge la communication asynchrone et un modèle de publication/abonnement.
Vous pouvez utiliser des événements pour implémenter des transactions métier qui s’étendent sur plusieurs services, ce qui vous donne une cohérence éventuelle entre ces services. Une transaction cohérente se compose d’une série d’actions distribuées. À chaque action, le microservice met à jour une entité métier et publie un événement qui déclenche l’action suivante. Notez que les transactions ne s’étendent pas à la persistance sous-jacente et au bus d’événements. Il est donc nécessaire de gérer l’idempotence. La figure 6-18 ci-dessous montre un événement PriceUpdated publié par le biais d’un bus d’événements, de sorte que la mise à jour des prix est propagée au panier et à d’autres microservices.
Figure 6-18. Communication pilotée par les événements et basée sur un bus d’événements
Cette section décrit comment implémenter ce type de communication avec .NET à l’aide d’une interface de bus d’événements générique, comme illustré dans la figure 6-18. Il existe plusieurs implémentations potentielles, chacune utilisant une technologie ou une infrastructure différente, comme RabbitMQ, Azure Service Bus, ou tout autre service open source ou commercial tiers.
Utilisation de répartiteurs de messages et de bus de service pour les systèmes de production
Comme indiqué dans la section architecture, vous pouvez choisir parmi plusieurs technologies de messagerie pour implémenter votre bus d’événements abstrait. Mais ces technologies sont à différents niveaux. Par exemple, RabbitMQ, un agent de messagerie, se situe à un niveau inférieur aux produits commerciaux tels que Azure Service Bus, NServiceBus, MassTransit ou Brighter. La plupart de ces produits peuvent fonctionner sur RabbitMQ ou Azure Service Bus. Votre choix de produit dépend du nombre de fonctionnalités et de la scalabilité prête à l’emploi dont vous avez besoin pour votre application.
Pour réaliser une simple preuve de concept d'un bus d'événements pour votre environnement de développement, comme dans l'exemple eShopOnContainers, une implémentation simple reposant sur RabbitMQ exécuté en tant que conteneur peut suffire. Toutefois, pour les systèmes stratégiques et de production nécessitant une scalabilité élevée, vous pouvez évaluer et utiliser Azure Service Bus.
Si vous avez besoin d’abstractions de haut niveau et de fonctionnalités plus riches comme Sagas pour les processus de longue durée qui facilitent le développement distribué, d’autres bus de service commerciaux et open source tels que NServiceBus, MassTransit et Brighter méritent d’être évalués. Dans ce cas, les abstractions et l’API à utiliser sont généralement directement celles fournies par ces bus de service de haut niveau au lieu de vos propres abstractions (comme les abstractions de bus d’événements simples fournies à eShopOnContainers). Pour cela, vous pouvez rechercher les eShopOnContainers forked à l’aide de NServiceBus (exemple dérivé supplémentaire implémenté par Particular Software).
Bien sûr, vous pouvez toujours créer vos propres fonctionnalités service bus sur des technologies de bas niveau 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.
Pour répéter : les exemples d’abstractions et d’implémentation de bus d’événements présentés dans l’exemple eShopOnContainers sont destinés à être utilisés uniquement comme preuve de concept. Une fois que vous avez décidé d’avoir une communication asynchrone et pilotée par les événements, comme expliqué dans la section actuelle, vous devez choisir le produit Service Bus qui répond le mieux à vos besoins en production.
Événements d’intégration
Les événements d’intégration sont utilisés pour synchroniser l’état du domaine sur plusieurs microservices ou systèmes externes. Cette fonctionnalité est effectuée en publiant des événements d’intégration en dehors du microservice. Lorsqu’un événement est publié sur plusieurs microservices récepteurs (à autant de microservices que ceux qui sont abonnés à l’événement d’intégration), le gestionnaire d’événements approprié dans chaque microservice récepteur gère l’événement.
Un événement d’intégration est essentiellement une classe de conservation des données, comme dans l’exemple suivant :
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 sorte qu’ils sont découplés d’autres microservices, de manière comparable à la façon dont Les ViewModels sont définis dans le serveur et le client. Ce qui n’est pas recommandé, c’est de partager une bibliothèque d’événements d’intégration commune sur plusieurs microservices ; cela permettrait de couplage de ces microservices avec une bibliothèque de données de définition d’événement unique. Vous ne souhaitez pas le faire pour les mêmes raisons que pour lesquelles vous ne souhaitez pas partager un modèle de domaine commun sur plusieurs microservices : les microservices doivent être complètement autonomes. Pour plus d’informations, consultez ce billet de blog sur la quantité de données à placer dans des événements. Veillez à ne pas aller trop loin, comme le décrit cet autre billet de blog le problème que peuvent causer les messages déficients en données. La conception de vos événements doit viser à être « idéal » pour les besoins de leurs consommateurs.
Il n’existe que quelques types de bibliothèques que vous devez partager entre les microservices. Il s’agit de bibliothèques qui sont des blocs d’application finaux, comme l’API cliente Event Bus, comme dans eShopOnContainers. Il s’agit également de bibliothèques qui constituent des outils qui peuvent également être partagés en tant que composants NuGet, comme les sérialiseurs JSON.
Bus d’événements
Un bus d’événements permet une communication de type publication/abonnement entre les microservices sans exiger que les composants soient explicitement conscients les uns des autres, comme illustré dans la figure 6-19.
Figure 6-19. Principes de base de la communication de type publication/abonnement avec un bus d’événements
Le diagramme ci-dessus montre que le microservice A publie sur le bus d'événements, qui distribue aux microservices abonnés B et C, sans que l’éditeur ait besoin de connaître les abonnés. Le bus d’événements est lié au modèle Observer et au modèle publish-subscribe.
Modèle d’observateur
Dans le modèle Observer, votre objet principal (appelé observable) avertit d’autres objets intéressés (appelés Observateurs) avec des informations pertinentes (événements).
Modèle Publier/S’abonner (Pub/Sub)
L’objectif du modèle Publier/s’abonner est le même que le modèle Observer : vous souhaitez notifier d’autres services lorsque certains événements ont lieu. Mais il existe une différence importante entre les modèles Observer et Pub/Sub. Dans le modèle d’observateur, la diffusion est effectuée directement à partir de l’observable aux observateurs, de sorte qu’ils « connaissent » les uns les autres. Toutefois, lors de l’utilisation d’un modèle Pub/Sub, il existe un troisième composant, appelé répartiteur ou répartiteur de messages ou bus d’événements, connu à la fois par l’éditeur et l’abonné. Par conséquent, lors de l’utilisation du modèle Pub/Sub, l’éditeur et les abonnés sont précisément découplés grâce au bus d’événements ou au répartiteur de messages mentionné.
L’intermédiaire ou le bus d’événements
Comment obtenir l’anonymat entre l’éditeur et l’abonné ? Un moyen simple est de laisser un intermédiaire prendre soin de toutes les communications. Un bus d’événements est un tel intermédiaire.
Un bus d’événements se compose généralement de deux parties :
Abstraction ou interface.
Une ou plusieurs implémentations.
Dans la figure 6-19, vous pouvez voir comment, du point de vue de l’application, le bus d’événements n’est rien de plus qu’un canal Pub/Sub. La façon dont vous implémentez cette communication asynchrone peut varier. Il peut avoir plusieurs implémentations afin que vous puissiez les échanger en fonction des exigences de l’environnement (par exemple, des environnements de production et de développement).
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.
Figure 6- 20. Implémentations multiples d’un bus d’événements
Il est judicieux que le bus d’événements soit défini par le biais d’une interface afin qu’il puisse être implémenté avec plusieurs technologies, telles que RabbitMQ, Azure Service bus ou d’autres. Toutefois, et comme mentionné précédemment, l’utilisation de vos propres abstractions (interface de bus d’événements) est bonne uniquement si vous avez besoin de fonctionnalités de bus d’événements de base prises en charge par vos abstractions. Si vous avez besoin de fonctionnalités service bus plus riches, vous devez probablement utiliser l’API et les abstractions fournies par votre bus de service commercial préféré au lieu de vos propres abstractions.
Définition d’une interface de bus d’événements
Commençons par un code d’implémentation pour l’interface de bus d’événements et les implémentations possibles à des fins d’exploration. L’interface doit être générique et simple, comme dans l’interface suivante.
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 Publish
méthode est simple. Le bus d’événements diffusera l’événement d’intégration transmis à n’importe quel microservice, voire à une application externe, abonné à cet événement. Cette méthode est utilisée par le microservice qui publie l’événement.
Les Subscribe
méthodes (vous pouvez avoir plusieurs implémentations en fonction des arguments) sont utilisées par les microservices qui souhaitent recevoir des événements. Cette méthode a deux arguments. Le premier est l’événement d’intégration auquel s’abonner (IntegrationEvent
). Le deuxième argument est le gestionnaire d’événements d’intégration (ou méthode de rappel), nommé IIntegrationEventHandler<T>
, à exécuter lorsque le microservice récepteur obtient ce message d’événement d’intégration.
Ressources supplémentaires
Certaines solutions de messagerie prêtes pour la production :
Azure Service Bus
https://learn.microsoft.com/azure/service-bus-messaging/NServiceBus
https://particular.net/nservicebusMassTransit
https://masstransit-project.com/