web-dev-qa-db-fra.com

Amazon Kinesis et AWS Lambda réessaye

Je suis très nouveau sur Amazon Kinesis alors peut-être que c'est juste un problème dans ma compréhension mais dans le FAQ AWS Lambda it dit:

Les enregistrements Amazon Kinesis et DynamoDB Streams envoyés à votre fonction AWS Lambda sont strictement sérialisés, par fragment. Cela signifie que si vous placez deux enregistrements dans le même fragment, Lambda garantit que votre fonction Lambda sera invoquée avec succès avec le premier enregistrement avant d'être invoquée avec le deuxième enregistrement. Si l'appel pour un enregistrement arrive à expiration, est limité ou rencontre une autre erreur, Lambda réessayera jusqu'à ce qu'il réussisse (ou jusqu'à ce que l'enregistrement atteigne son expiration de 24 heures) avant de passer à l'enregistrement suivant. L'ordre des enregistrements sur différents fragments n'est pas garanti et le traitement de chaque fragment se déroule en parallèle.

Ma question est, que se passe-t-il si, pour une raison quelconque, des données malformées sont mises sur un fragment par un producteur et lorsque la fonction Lambda les détecte, il y a des erreurs et continue simplement à réessayer constamment? Cela signifie alors que le traitement de ce fragment particulier serait bloqué pendant 24 heures par l'erreur.

La meilleure pratique consiste-t-elle à gérer les erreurs d'application de cette manière en enveloppant le problème dans une erreur personnalisée et en envoyant cette erreur en aval avec tous les enregistrements traités avec succès et en laissant le consommateur la gérer? Bien sûr, cela n'aiderait toujours pas dans le cas d'une erreur irrécupérable qui plantait le programme comme un pointeur nul: nous serions de nouveau de retour à la boucle de nouvelle tentative de blocage pour les prochaines 24 heures.

22
Stefano

N'y pensez pas trop, le Kinesis n'est qu'une file d'attente. Vous devez consommer un enregistrement (c'est-à-dire pop de la file d'attente) avec succès afin de passer au suivant. Tout comme une pile FIFO.

L'approche appropriée devrait être:

  • Obtenez un enregistrement du flux.
  • Traitez-le dans un bloc try-catch-finally.
  • Si l'enregistrement est traité avec succès, aucun problème. <- ESSAYER
  • Mais s'il échoue, notez-le dans un autre endroit pour rechercher la raison de l'échec. <- CAPTURE
  • Et à la fin de vos blocs logiques, conservez toujours la position dans DynamoDB. <- ENFIN
  • Si un problème interne se produit dans votre système (erreur de mémoire, erreur matérielle, etc.), c'est une autre histoire; car cela peut affecter le traitement de tous les enregistrements, pas un seul.

Soit dit en passant, si le traitement d'un enregistrement prend plus d'une minute, il est évident que vous faites quelque chose de mal. Parce que Kinesis est conçu pour gérer des milliers d'enregistrements par seconde, vous ne devriez pas avoir le luxe de traiter des tâches aussi longues pour chacun d'eux.

La question que vous posez est un problème général des systèmes de files d'attente, parfois appelé "message toxique". Vous devez les gérer dans votre logique métier pour être en sécurité.

http://www.cogin.com/articles/SurvivingPoisonMessages.php#PoisonMessages

32
az3

Il s'agit d'une question courante sur le traitement des événements dans Kinesis et je vais essayer de vous donner quelques points pour créer votre fonction Lambda pour gérer ces problèmes avec des données "corrompues". Comme il est préférable d'avoir des parties séparées de votre système écrivant dans le flux Kinesis et d'autres parties lisant dans le flux Kinesis, il est courant que vous rencontriez de tels problèmes.

Tout d'abord, pourquoi avez-vous de tels événements problématiques ?

Utiliser Kinesis pour traiter vos événements est un bon moyen de diviser un système complexe qui effectue à la fois le traitement frontal (au service des utilisateurs finaux) et en même temps/le traitement principal du code (analyse des événements), en deux parties indépendantes de votre système. Les personnes frontales peuvent se concentrer sur leur entreprise, tandis que les personnes back-end n'ont pas besoin de pousser les modifications de code vers le front-end, si elles veulent ajouter des fonctionnalités pour servir leurs cas d'utilisation analytiques. Kinesis est un tampon d'événements qui à la fois rompt le besoin de synchronisation et simplifie le code logique métier.

Par conséquent, nous aimerions que les événements écrits dans le flux soient flexibles dans leur " schéma", et si les équipes frontales souhaitent changer le format de l'événement, ajouter des champs, supprimer des champs, changer le protocole ou les clés de chiffrement, ils devraient pouvoir le faire aussi souvent qu'ils le souhaitent.

Il appartient désormais aux équipes qui lisent dans le flux de pouvoir traiter ces événements flexibles de manière efficace et de ne pas interrompre leur traitement chaque fois qu'un tel changement se produit. Par conséquent, il devrait être courant que votre fonction Lambda voit des événements qu'elle ne peut pas traiter, et " poison-pill " n'est pas cet événement rare comme vous pourriez vous attendre.

Deuxièmement, comment gérez-vous ces événements problématiques?

Votre fonction Lambda recevra un lot d'événements à traiter. Veuillez noter que vous ne devriez pas obtenir les événements un par un, mais en grands lots d'événements. Si vos lots sont trop petits, vous obtiendrez rapidement de gros retards sur le flux.

Pour chaque lot, vous itérerez sur les événements, les traiterez puis vérifierez dans DynamoDB le dernier ID de séquence du lot. Lambda effectue la plupart de ces étapes automatiquement avec (voir plus ici: http://docs.aws.Amazon.com/lambda/latest/dg/walkthrough-kinesis-events-adminuser-create-test-function). html ):

console.log('Loading function');

exports.handler = function(event, context) {
    console.log(JSON.stringify(event, null, 2));
    event.Records.forEach(function(record) {
        // Kinesis data is base64 encoded so decode here
        payload = new Buffer(record.kinesis.data, 'base64').toString('ascii');
        console.log('Decoded payload:', payload);
    });
    context.succeed();
};

C'est ce qui se passe dans le "chemin heureux", si tous les événements sont traités sans aucun problème. Mais si vous rencontrez un problème dans le lot et que vous ne "" validez "les événements avec la notification de réussite, le lot échouera et vous obtiendrez à nouveau tous les événements du lot.

Vous devez maintenant décider quelle est la raison de l'échec du traitement.

  • Problème temporaire (limitation, problème de réseau ...) - il est OK d'attendre une seconde et de réessayer plusieurs fois. Dans de nombreux cas, le problème se résoudra de lui-même.

  • Problème occasionnel (manque de mémoire ...) - il est préférable d'augmenter l'allocation mémoire de la fonction Lambda ou de diminuer la taille du lot. Dans de nombreux cas, une telle modification résoudra le problème.

  • Échec constant - cela signifie que vous devez soit ignorer l'événement problématique (le mettre dans une file d'attente de lettres mortes DLQ), soit modifier votre code pour gérer.

Le problème est d'identifier le type d'échec dans votre code et de le gérer différemment. Vous devez écrire votre code Lambda de manière à l'identifier (type d'exception, par exemple) et réagir différemment.

Vous pouvez utiliser l'intégration avec CloudWatch pour écrire de tels échecs sur la console et créer les alarmes pertinentes. Vous pouvez également utiliser les journaux CloudWatch pour enregistrer votre "file d'attente de lettres mortes" et voir quelle est la source du problème.

16
Guy