Les micro-services : indéniablement un sujet à la mode 🤙.

La logique derrière un micro-service (et elle a été détournée plusieurs fois), c'est d'être responsable d'une petite action business (j'irais presque à dire que c'est serverless 🤐).

On voit souvent l'utilisation du terme micro-service alors qu'au final, on a affaire à un système SOA (Service Oriented Architecture) avec des vrais services et non pas des micro-services. Mais là n'est pas le sujet.

Dans un système orienté service, il y a un élément central si on désire réellement avoir des services autonomes et indépendant, c'est le sujet de la communication 👂

Alors oui, il y a plusieurs patterns, chacun avec leurs avantages et leurs inconvénients. Un des patterns les plus connus est d'utiliser un message broker, ou un bus de message afin de permettre aux services de communiquer entre eux.

Je n'entrererai pas dans le détails de cette communication dans ce billet (le sujet est très vaste et super intéressant 😍) mais ce sur quoi je vais prendre un peu de temps est le résilience.

En effet, dès lors qu'un service a effectué une action, on va considérer qu'il émettra un message sur le bus et que d'autres services vont écouter le même bus pour récupérer ce message et le traiter.

Messaging

Oui, j'avoue, j'ai eu du mal à trouver où caler un gif cette fois-ci 😁

Bref ! De ce fait, lorsqu'un service a émis son message, il va généralement "oublier" ce qu'il a émis (on peut sécuriser ça côté envoi aussi, mais c'est pas le sujet ici !).

Il y a plusieurs outils pour faire le bus de communication (RabbitMQ, Kafka, Azure Service Bus, AWS Event Bridge pour citer les plus connus). Là, je vais prendre un peu de temps sur Azure Service Bus.

Alors oui, il est nécessaire que vous récupériez les messages de façon intelligente pour profiter de ces paramètres là, mais avant ça, c'est quand même mieux de les connaitre 😊 !

Azure Service Bus offre plusieurs paramètre de configuration au niveau des queues. Déjà, le premier, on peut fixer une durée de vie, c'est à dire qu'un message restera valide dans une queue pendant X temps (à définir) et qu'une fois qu'il périme, il bascule en dead letter queue. Le message n'est donc pas perdu (généralement, on met sur la dead letter une durée de vie très longue pour avoir le temps de faire la maintenance).

Après, il y a deux autres facteurs sur lesquels il faut jouer pour qu'un message parte en dead-letter :

  • Le lock duration
  • Le maximum delivery count

Le premier permet d'indiquer pendant combien de temps un lock pris par quelqu'un dure avant de périmer. Pour comprendre cette notion, il faut savoir qu'il y a deux façons de consommer un message depuis un bus :

  1. soit on fait un receive, c'est à dire qu'on supprime le message dès qu'on l'a lu
  2. soit on fait un peek-lock, c'est à dire qu'on récupère le message ainsi que son lock et on détermine quand on supprime le message grâce au lock token

Il va sans dire que si vous avez fait le choix de faire un receive "simple", vous allez avoir le maximum de perf au niveau bus (la queue ne sera jamais saturée ou alors faut vraiment le vouloir 🤯) mais aussi le minimum de résilience, car c'est au consommateur de s'assurer qu'il ne perdra pas l'info.

A titre personnel, je n'ai pas confiance aux consommateurs (surtout si c'est moi qui l'ai codé 🤣), du coup, je recommande fortement de ne faire que des peek-lock.

Mais voilà, une fois qu'on a fait un peek-lock, on a placé un verrou qui va durer x secondes/minutes (selon ce que vous avez configuré) ce qui veut dire que n'importe quel autre consommateur verra le message mais ne pourra pas le consommer (bon, normalement, il ne devrait y avoir qu'un seul consommateur, donc dans l'idée, vous ne recevrez pas ce message tant qu'il est lock).

Une fois que votre traitement est ok, vous pouvez le supprimer avec le lock token, ainsi, vous vous servez de la queue comme stockage de sécurité, vous assurant que le message reste bien présent tant que vous ne l'avez pas traité avec succès.

Et ce qui est beau, c'est que la façon dont c'est configuré, quand votre lock expire, vous allez récupérer votre message (typiquement, si vous rencontrez une erreur dans votre traitement qui fait que vous n'allez pas supprimer le message, c'est l'expiration du lock côté bus qui va jouer son rôle). Sauf que là, vous allez le récupérer avec une propriété intéressante : le delivery count.

En effet, Azure Service Bus compte le nombre de fois où il a délivré le message. Ainsi, vous avez un système de retry naturel, ce qui fait qu'en jouant sur ces deux paramètres, vous pouvez tenter un réessai sans avoir de faire de manoeuvres particulières de votre côté ... C'en est presque magique 🧙 !

Bien entendu, ce cas de figure ne correspond à toutes les situations et dans certains cas, ce n'est pas la bonne façon de faire (par exemple si le message a une durée de validité très courte). Mais c'est toujours bon de savoir ce genre de chose.

De notre côté, vu qu'on bosse sur un provider CQELight 🚀 pour Azure Service Bus, c'est des choses qu'on doit prendre en compte, mais il faut qu'on conserve le côté générique pour que ça marche aussi avec tous les autres providers, donc pas une mince affaire !

Comments


Comments are closed