Circuits breakers dans une architecture microservices :
Dans cet article nous allons définir ce qu’est un circuit break, ses différents états et le rôle que joue ce dernier dans la communication entre services.
Qu’est ce qu’un circuit breaker :
Sur cette image, nous pouvons voir un disjoncteur, nous en avons tous un chez nous, il est indispensable pout tout montage électrique. Son rôle est de couper le circuit au cas où il y aurait la surcharge d’un certain composant.
Il se trouve que c’est à peu près la même chose pour les court circuit en informatique.
Les circuit breakers en informatique :
Chaque fois que nous faisons appel à un service, un thread se charge d’envoyer une requête et d’attendre la réponse du service :
Si, pour une certaine raison, il y a une erreur dans le service de réception, le thread chargé de la requête en question se verra attendre indéfiniment la réponse du service auquel la requête est envoyée. Ensuite, on envoie une deuxième requête avec un deuxième thread et une erreur se produit, ce dernier se retrouve bloquée. Maintenant supposons que nous avons beaucoup trop d’erreur et que tous les threads sont bloqués. Tous en train d’attendre une réponse du service demandé, une exception de type Timeout failure est alors declanchée.
Puisqu’aucun des threads du threadPool n’est disponible, le service qui envoyait les requêtes, ne pourra plus rien envoyer vers aucun autre service. Comme d’autres services peuvent être dépendant de ce dernier, les erreurs se propagent partout dans l’application, et se cumulent jusqu’à provoquer une défaillance globale.
Par exemple : un service Commande fait appel au service Livraison afin d’avoir l’adresse de certains clients (une requête et un thread par client). Si la base de données du service de livraison rencontre certains problèmes et que le service de Livraison ne peut pas répondre aux requêtes envoyées par le service Commande, retournant une exception “NotFound”, alors, les threads restent tous bloqués. Le service de Commande ne peut plus faire de requêtes vers aucun autre service. Maintenant, si le service Stock veut connaître les quantités de certains produits et qu’il fait appel au service Commande. Ce dernier, étant en time-out failure, ne peut ni répondre ni envoyé d’autres requêtes. Le service Stock va à son tour échouer et passer en time-out. C’est ainsi que les erreurs se propagent de service en service jusqu’à tous faire exploser !!
Afin d’empêcher qu’un tel scénrio se produise, nous mettons en place un Circuit Breaker, qui empêche la propagation d’erreurs entre services.
Comment ça marche ?
Lorsqu’un nombre d’erreurs maximum est atteint ( pouvant être définis dans le fichier de configuration de chaque service par défaut égale à 10) le Circuit-breaker passe en état ouvert. Dans cet état, toutes les requêtes envoyées vers le service défaillant sont mise de côté, en stand-by. Durant une certaine période appelée “call-timeout” (configurable dans le fichier conf par défaut égal à 60).
Une fois ce laps de temps écoulé, le circuit breaker passe en état semi-ouvert et prends la premier requête défaillante et l’execute, si elle se termine avec succès, le circuit breaker bascule vers son état normal ( fermé ). Sinon, le circuit breaker rebascule vers l’état ouvert.
La White-liste :
Dans beaucoup de framework, les retours de requêtes de type 4xx et 5xx sont considérés comme étant des erreurs, et peuvent provoquer l’ouverture d’un circuit breaker.
Parfois, certaines exceptions ne valent pas la peine de déclencher un tel chahut. Il est, possible d’ajouter le fichier de configuration de chaque service une liste d’erreurs qui sont à ignorer par le compilateur pour ne pas declencher l’ouverture d’un circuit breaker.
Conclusion :
- Les circuits breakers sont là pour empêcher la propagation d’erreurs entre services.
- Le circuit breaker a 3 états : fermé, semi-ouvert et ouvert
- les circuits breaker passent en état ouvert après que le nombre d’erreur est dépassé le paramètre max-failure prédéfini dans le fichier de configuration du service.
- Les circuits breaker passent en état ouvert pendant un certain laps de temps appelé “Call-timeout. Après cellui-ci, le circuit breaker passe en état semi-ouvert.
- En état semi-ouvert les circuits breakers prennent la première requête qui avait échouée et l’envoie. Si les threads retournent une réponse valide, ce dernier bascule vers l’état fermé (son état par défaut). Sinon les circuits breakers repassent en état ouvert pendant un autre call-timeout.
- Il est possible d’ignorer certaines exceptions pour ne pas causer un circuit breaker non pertinent; pour cela il est nécessaire d’ajouter ces erreurs dans une white liste, dans le fichier conf du service.