Aller directement à la fin des métadonnées
Aller au début des métadonnées

Comme indiqué dans le billet "Vers une infrastructure en micro services", Gadz.org s'oriente vers une architecture en micro service. J'expose ici les problèmes que cela pose pour la gestion des erreurs.

Classification des erreurs

Lors du traitement d'un message, un service consommateur peut rencontrer des erreurs. Il s'agit d’événement empêchant le traitement correct du message.

On sépare trois 3 natures d'erreurs :

Les erreurs "métier"

 Il s'agit d'erreurs liées à la logique métier du service. Exemples : inscription d'un utilisateur à une liste de diffusion dont il fait déjà partit, attribution d'une adresse mail déjà attribuée...

Les erreurs "techniques"

Ce sont des erreurs qui apparaissent lors de l'execution du service. Exemples : Reception d'un message ne respectant pas le format défini les spécifications, bug du à un caractère invalid ou tout autre bug provoquant l’interruption involontaire du service.

Les erreurs de disponibilité

Elles interviennent lorsqu'une ressource extérieure nécessaire au traitement du message n'est pas disponible. Exemple : base de donnée indisponible, accès aux API Google suite à un dépassement de quota, etc. Ces erreurs sont parfois considérées comme un cas particulier des erreurs techniques.

 

Il est également possible de classer les erreurs en 2 types :

Les erreurs remédiables

Une erreur est dite remédiable lorsque le meme message peut être traiter en reessayant plus tard ou en étant traiter d'une autre manière (eventuellement en l'envoyant à un autre service)

Les erreurs irdiables

Les erreurs irrémédiables sont dues à la nature même du  message ou à l'implémentation technique du service. Ce message ne pourra jamais être traiter

Les erreurs de disponibilité sont généralement remédiable. A l'inverse, les erreurs technique sont souvent irrémédiables.

La gestion des erreurs

Première approche

Dans une première approche, nous avons choisi une solution simple de la gestion des erreurs. Nous ne considérons que 2 types d'erreurs : les erreurs remédiables (Softfail) et les erreurs irrémédiables (Hardfail). Il s'agit d'une généralisation de l'approche utilisée par les X lors du développement de GappsD [Github] notre ancien système de synchronisation GoogleApps. Les règles sont les suivantes :

  • Lors d'un Hardfail, le message est abandonné et simplement transmis au système de log centralisé pour en garder une trace
  • Lors d'un Softfail, le message est stocké dans une zone tampon pour être réinjecté automatiquement dans le système après une certaine période (30 minutes par défaut). Un Hardfail est déclenché au bout de 10 tentatives.

La zone tampon est indépendante du service qui a provoqué l'erreur. En pratique, nous utilisons une queue RabbitMQ ayant une date d'expiration [documentation technique]

Voici un exemple d'utilisation : 



Cet exemple illustre le fonctionnement de l'appel à un service GoogleApps Service chargé de créer des compte Google en utilsant les API de Google. Le service est appelé explicitement via l'utilisation de la clé de routage "request.googleapps.user.create"

Etapes :

  1. Gram Producer envoie un message avec la clé de routage "request.googleapps.user.create" à l'exchange Agoram Exchange
  2. Le message est transmis aux queue abonnée à la clé de routage "request.googleapps.user.create". Ici seulement la queue GoogleAppsService Queue
  3. Le message est stocké dans la queue GoogleAppsService Queue en attendant que GoogleAppsService le récupère
  4. GoogleAppsService récupère le message et le traite. Les API Google n'étant pas disponibles, une erreur Softfail est levée.
  5. Cette erreur est ajoutée au contenu du message
  6. Le message est envoyé dans la queue GoogleAppsService Deferred Queue via GoogleAppsService Producer
  7. Après 30 minutes, le message est renvoyé dans l'exchange Agoram Exchange avec la clé de routage d'origine : "request.googleapps.user.create"
  8. Les étapes 2 à 7 sont répétées jusqu'à ce que l'API Google soit de nouveau disponible ou que 10 erreurs Softfails soient inscrites dans le message
  9. Si 10 erreurs Softfail soient inscrites dans le message, le message est envoyé dans l'exchange avec la clés de routage "agoram.log"

Cette approche à plusieurs avantages :

  • L'ensemble des messages transitant via l'exchange principal étant loguées, toutes les erreurs sont logguées de manière centralisée. La detection des défaillance est donc facilité. Le service peut de sont coté avoir ses propres logs. 
  • La gestion de la zone tampon n'est pas confié au service mais au système de messagerie via une approche standard. Cela permet d'éviter qu'une défaillance du service n’entraîne une perte des messages.
  • Elle est relativement simple à mettre en place et monitorer.

Limitations

Mais cette approche ne fonctionne que dans un cas très précis : le message ne peut exister qu'à un seul endroit à la fois. Il ne peut pas être dupliquer pour être envoyé à plusieurs services simultanément.

Prenons un autre exemple pour mieux comprendre le problème :

Dans cet exemple nous changeons de fonctionnement. Plutôt que d'appeler explicitement les services, nous utilisons un système de "notification". A chaque nouvel utilisateur enregistré dans l'application GrAM, un message avec la clé de routage "notify.gram.user.created" est envoyé. Les services abonnés à cette notification recevront le message. Dans cet exemple, 2 services sont abonnés à "notify.gram.user.created" :

  • GoogleApps Service, chargé de la création des comptes Google
  • WelcomeMail Service, chargé d'envoyer un mail de bienvenu aux nouveaux inscrit avec toutes les informations leur étant necessaire

Reprenons le fonctionnement précédent :

  1. Gram Producer envoie un message avec la clé de routage "notify.gram.user.created" à l'exchange Agoram Exchange
  2. Le message est transmis aux queue abonnée à la clé de routage "notify.gram.user.created". Ici, il s'agit des queues GoogleApps Service Queue et WelcomeMail Service Queue
  3. Le message est dupliqué et stocké dans les queue en attendant que les différents services le récupère
  4. WelcomeMail Service récupère le message et le traite. Un mail est envoyé à l'utilisateur
  5. GoogleAppsService récupère le message et le traite. Les API Google n'étant pas disponibles, une erreur Softfail est levée.
  6. Cette erreur est ajoutée au contenu du message
  7. Le message est envoyé dans la queue GoogleAppsService Deferred Queue via GoogleAppsService Producer
  8. Après 30 minutes, le message est renvoyé dans l'exchange Agoram Exchange avec la clé de routage d'origine : "notify.gram.user.created"
  9. Les étapes 2 à 8 sont répétées jusqu'à ce que l'API Google soit de nouveau disponible ou que 10 erreurs Softfails soient inscrites dans le message
  10. Si 10 erreurs Softfail soient inscrites dans le message, le message est envoyé dans l'exchange avec la clés de routage "agoram.log"

En suivant ce protocole, un nouveau mail est envoyé à chaque Softfail généré par GoogleApps Service. De plus, si des erreurs apparaissent simultanément dans plusieurs services, l'historique des erreurs présent dans le contenu du messages ne sera pas cohérent entre les différentes instances de ce message.

Plus généralement, ceci pose la question du traitement des Softfails. Doit-on ré-effectuer toutes les actions ou uniquement celles en erreur ?

Une autre approche est donc necessaire. Les différentes solutions envisagées feront l'objet d'un autre billet de blog.

N'hésitez pas à participer et proposer des solutions via les commentaires ou sur le Slack de Gadz.org

  • Aucune étiquette