Partage via


Traitement fiable des événements avec Azure Functions et Event Hubs

Découvrez comment créer des solutions serverless robustes et fiables à l’aide d’Azure Functions avec des déclencheurs Azure Event Hubs. Cet article traite des meilleures pratiques pour les points de contrôle, la gestion des erreurs et l’implémentation de modèles disjoncteur pour vous assurer qu’aucun événement n’est perdu et que vos applications pilotées par les événements restent stables et résilientes.

Défis liés aux flux d’événements dans les systèmes distribués

Considérez un système qui envoie des événements à un taux constant de 100 événements par seconde. À ce taux, dans les minutes, plusieurs instances parallèles peuvent consommer les 100 événements entrants toutes les secondes.

Toutefois, tenez compte de ces défis liés à l’utilisation d’un flux d’événements :

  • Un éditeur d’événements envoie un événement endommagé.
  • Votre code de fonction rencontre une exception non gérée.
  • Un système en aval est hors connexion et bloque le traitement des événements.

Contrairement à un déclencheur de stockage File d’attente Azure, qui verrouille les messages pendant le traitement, Azure Event Hubs lit, par partition, à partir d’un point unique dans le flux. Ce comportement de lecture, plus semblable à un lecteur vidéo, offre les avantages souhaités d’un débit élevé, de plusieurs groupes de consommateurs et de la capacité de relecture. Les événements sont lus, vers l’avant ou vers l’arrière, à partir d’un point de contrôle, mais vous devez déplacer le pointeur pour traiter de nouveaux événements. Pour plus d’informations, consultez Point de contrôle dans la documentation Event Hubs.

Lorsque des erreurs se produisent dans un flux et que vous choisissez de ne pas avancer le pointeur, le traitement des événements supplémentaire est bloqué. En d’autres termes, si vous arrêtez le pointeur pour traiter un problème de traitement d’un événement unique, les événements non traités commencent à s’accumuler.

Les fonctions évitent les blocages en faisant toujours avancer le pointeur du flux, quel que soit le succès ou l’échec. Étant donné que le pointeur continue de progresser, vos fonctions doivent gérer les défaillances de manière appropriée.

Comment le déclencheur Event Hubs consomme les événements

Azure Functions consomme des événements à partir d’un hub d’événements en parcourant les étapes suivantes :

  1. Un pointeur est créé et conservé dans stockage Azure pour chaque partition du hub d’événements.
  2. De nouveaux événements sont reçus dans un lot (par défaut) et l’hôte tente de déclencher la fonction fournissant un lot d’événements à traiter.
  3. Lorsque la fonction termine l’exécution, avec ou sans exceptions, le pointeur est avancé et un point de contrôle est enregistré dans le compte de stockage hôte par défaut.
  4. Si les conditions empêchent l’exécution de la fonction, l’hôte ne peut pas avancer le pointeur. Lorsque le pointeur ne peut pas avancer, les exécutions suivantes retraitent les mêmes événements.

Ce comportement révèle quelques points importants :

  • Les exceptions non gérées peuvent entraîner la perte d’événements :

    Les exécutions de fonctions qui déclenchent une exception continuent à faire progresser le pointeur. La définition d’une stratégie de nouvelle tentative ou d’une autre logique de nouvelle tentative retarde l’avancement du pointeur jusqu’à la fin de la nouvelle tentative.

  • Functions garantissent une livraison au moins une fois :

    Votre code et vos systèmes dépendants peuvent avoir besoin de tenir compte du fait que le même événement peut être traité deux fois. Pour plus d’informations, consultez Conception d’Azure Functions pour une entrée identique.

Gestion des exceptions

Même si tous les codes de fonction devraient inclure un bloc try/catch au niveau le plus élevé du code, il est encore plus important d’avoir un bloc catch pour les fonctions qui utilisent les événements Event Hubs. De cette façon, lorsqu’une exception est levée, le bloc de traitement des exceptions gère l’erreur avant que le pointeur ne progresse.

Mécanismes et stratégies de nouvelle tentative

Étant donné que de nombreuses exceptions dans le cloud sont temporaires, la première étape de la gestion des erreurs consiste toujours à réessayer l’opération. Vous pouvez appliquer des stratégies de nouvelle tentative intégrées ou définir votre propre logique de nouvelle tentative.

Stratégies de nouvelle tentative

Functions fournit des stratégies de nouvelle tentative intégrées pour Event Hubs. Lorsque vous utilisez des stratégies de nouvelle tentative, vous déclenchez simplement une nouvelle exception et l’hôte tente de réexécuter l’événement en fonction de la stratégie définie. Ce comportement de nouvelle tentative nécessite la version 5.x ou ultérieure de l’extension Event Hubs. Pour plus d’informations, consultez Stratégies de relance.

Logique de nouvelle tentative personnalisée

Vous pouvez également définir votre propre logique de nouvelle tentative dans la fonction elle-même. Par exemple, vous pouvez implémenter une stratégie qui suit un flux de travail illustré par les règles suivantes :

  • Essayez de traiter un événement trois fois (potentiellement avec un délai entre les nouvelles tentatives).
  • Si le résultat final de toutes les nouvelles tentatives est un échec, ajoutez un événement à une file d’attente afin que le traitement puisse continuer sur le flux.
  • Les événements corrompus ou non traités sont alors pris en charge ultérieurement.

Remarque

Polly est un exemple de bibliothèque de résilience et de gestion des erreurs temporaires pour les applications C#.

Erreurs non liées aux exceptions

Certains problèmes peuvent se produire sans qu’une exception soit levée. Par exemple, considérez un cas où une requête expire ou si l’instance exécutant la fonction se bloque. Lorsqu’une fonction ne parvient pas à se terminer sans exception, le pointeur de décalage n’est jamais avancé. Si le pointeur n’avance pas, alors toute instance qui s’exécute après l’échec d’exécution continue à lire les mêmes événements. Cette situation offre une garantie de remise au moins une fois.

L’assurance que chaque événement est traité au moins une fois implique que certains événements peuvent être traités plusieurs fois. Vos applications de fonction doivent être conscientes de cette possibilité et doivent être construites autour des principes d’idempotency.

Gestion des états d’échec

Votre application peut être en mesure de gérer de manière acceptable quelques erreurs dans le traitement des événements. Toutefois, vous devez également être prêt à gérer l’état d’échec persistant, ce qui peut se produire en raison d’échecs dans le traitement en aval. Dans un tel état de défaillance, telle qu’une banque de données en aval hors ligne, votre fonction doit cesser de se déclencher sur les événements jusqu’à ce que le système retrouve un état sain.

Modèle Disjoncteur

Lorsque vous implémentez le modèle disjoncteur , votre application peut interrompre efficacement le traitement des événements, puis la reprendre ultérieurement une fois les problèmes résolus.

Il existe deux composants requis pour implémenter un disjoncteur dans un processus de flux d’événements :

  • État partagé entre toutes les instances pour suivre et surveiller l’état de santé du circuit.
  • Un processus principal qui peut gérer l’état du circuit, soit comme open soit comme closed.

Les détails de l'implémentation peuvent varier, mais pour partager l'état entre les instances, vous avez besoin d'un mécanisme de stockage. Vous pouvez stocker l’état dans stockage Azure, un cache Redis ou tout autre service persistant accessible par vos instances d’application de fonction.

Durable Functions et Azure Logic Apps fournissent une infrastructure pour gérer les flux de travail et les états de circuit. Cet article décrit l’utilisation de Logic Apps pour suspendre et redémarrer les exécutions de fonction, ce qui vous donne le contrôle nécessaire pour implémenter le modèle disjoncteur.

Définir un seuil d’échec entre les instances

L’état externe partagé persistant est nécessaire pour surveiller l’intégrité du circuit lorsque plusieurs instances traitent simultanément des événements. Vous pouvez ensuite surveiller cet état persistant en fonction des règles qui indiquent un état d’échec, par exemple :

Lorsqu’il y a plus de 100 échecs d’événements au cours d’une période de 30 secondes sur toutes les instances, arrêtez le circuit pour arrêter le déclenchement de nouveaux événements.

Les détails de l’implémentation de cette logique de supervision varient en fonction des besoins de votre application, mais en général, vous devez créer un système qui :

  1. Journalise les échecs dans une mémoire persistante.
  2. Vérifiez le compte cumulatif lorsque de nouveaux échecs sont enregistrés pour déterminer si le seuil d'échec de l'événement est atteint.
  3. Lorsque ce seuil est atteint, émettez un événement indiquant au système de rompre le circuit.

Gestion de l’état du circuit avec Azure Logic Apps

Azure Logic Apps est fourni avec des connecteurs intégrés à différents services, fonctionnalités et orchestrations avec état, et convient tout naturellement à la gestion de l’état des circuits. Après avoir détecté quand un circuit doit s’arrêter, vous pouvez créer une application logique pour implémenter ce flux de travail :

  1. Déclenchez un flux de travail Event Grid qui arrête le traitement de la fonction.
  2. Envoyez un e-mail de notification qui inclut une option permettant de redémarrer le flux de travail.

Pour savoir comment désactiver et réactiver des fonctions spécifiques à l’aide des paramètres d’application, consultez Comment désactiver des fonctions dans Azure Functions.

Le destinataire de l’e-mail peut examiner l’intégrité du circuit et, le cas échéant, redémarrer le circuit via un lien dans l’e-mail de notification. Lorsque le flux de travail redémarre la fonction, les événements sont traités à partir du dernier point de contrôle event Hub.

Lorsque vous utilisez cette approche, aucun événement n’est perdu, les événements sont traités dans l’ordre et vous pouvez interrompre le circuit tant que nécessaire.

Stratégies de migration pour les déclencheurs Event Grid

Lorsque vous migrez une application de fonction existante entre des régions ou entre certains plans, vous devez recréer l’application pendant le processus de migration. Dans ce cas, pendant le processus de migration, vous pouvez avoir deux applications capables de consommer à partir du même flux d’événements et d’écrire dans la même destination de sortie.

Vous devez envisager d’utiliser des groupes de consommateurs pour éviter la perte ou la duplication des données d’événement pendant le processus de migration :

  1. Créez un groupe de consommateurs pour la nouvelle application cible.

  2. Configurez le déclencheur dans la nouvelle application pour utiliser ce nouveau groupe de consommateurs.

    Cela permet aux deux applications de traiter les événements indépendamment lors de la validation.

  3. Vérifiez que la nouvelle application traite correctement les événements.

  4. Arrêtez l’application d’origine ou supprimez son abonnement/groupe de consommateurs.