Bonnes pratiques pour les pipelines de lots volumineux

Ce document explique comment minimiser l'impact des échecs de tâches pour les grands pipelines par lot. Les défaillances de charges de travail importantes ont un impact particulièrement important en raison du temps et de l'argent nécessaires pour les récupérer et les corriger. Relancer ces pipelines à partir de zéro en cas d'échec est coûteux en termes de temps et d'argent.

Pour réduire les échecs coûteux du pipeline par lot, suivez les consignes de cette page. Étant donné que vous ne pouvez pas toujours éviter complètement les éléments défaillants et les défaillances de pipeline, les techniques fournies visent à augmenter la résilience, à réduire le coût des défaillances et à faciliter le débogage et la compréhension des défaillances lorsqu'elles se produisent.

Pour connaître les bonnes pratiques générales concernant les pipelines, consultez la section Bonnes pratiques pour les pipelines Dataflow.

Effectuer de petits tests pour de grandes tâches

Avant d'exécuter un job par lot volumineux, exécutez un ou plusieurs jobs plus petits sur un sous-ensemble de l'ensemble de données. Cette technique peut à la fois fournir une estimation des coûts et vous aider à identifier les points de défaillance potentiels.

Estimation du coût

L'exécution de tests peut fournir une estimation du prix plancher du coût total de l'exécution de la tâche. En règle générale, le calcul du coût de la tâche est cost of test job*size(full dataset)/size(test dataset). En fonction du pipeline, le coût peut évoluer de manière superlinéaire ou, plus rarement, sous-linéaire. Toutefois, cette étape fournit souvent une bonne estimation approximative du coût de la tâche. Vous pouvez également essayer différentes tailles d'entrées pour obtenir une meilleure estimation de l'évolution de vos coûts. Utilisez ces informations pour décider de poursuivre avec le pipeline existant ou de le réorganiser pour réduire les coûts.

Identifier les points de défaillance

L'exécution de tests peut révéler des bugs, des points de défaillance potentiels ou des problèmes de configuration et d'efficacité potentiels. Vous pouvez également examiner d'autres métriques de pipeline, telles que les suivantes:

  • Si votre pipeline utilise presque toute la mémoire disponible, il peut rencontrer des exceptions de mémoire insuffisante (OOM) en cas de charge plus élevée ou d'enregistrements exceptionnellement volumineux. Vous devrez peut-être provisionner plus de mémoire pour votre job final afin d'éviter ces erreurs OOM.
  • Si le débit de votre pipeline diminue, examinez les journaux de votre pipeline pour déterminer pourquoi. Vous pouvez trouver un élément bloqué ou une partie de votre ensemble de données présentant des performances particulièrement médiocres. Vous pouvez traiter ces points de données séparément ou appliquer un délai avant expiration lors du traitement des éléments. Pour en savoir plus, consultez la section Expiration des enregistrements coûteux de ce document.
  • Si les performances de votre pipeline sur une tâche dans Dataflow sont beaucoup moins bonnes qu'en local, examinez la logique de votre pipeline pour déterminer pourquoi. Par exemple, si vous obtenez le même débit avec huit cœurs sur Dataflow qu'avec un seul cœur en local, la tâche peut être limitée par la contention d'une ressource. Si vous constatez que vos performances sont inférieures à celles attendues, envisagez l'une ou plusieurs des options suivantes :
    • Effectuez d'autres tests avec différentes configurations matérielles ou logicielles.
    • Effectuez des tests en local avec plusieurs cœurs en même temps.
    • Inspectez votre code pour identifier les goulots d'étranglement potentiels lors du déploiement à grande échelle.

Si votre pipeline comporte des recommandations Dataflow, suivez-les pour améliorer ses performances.

Utiliser des files d'attente de lettres mortes pour gérer les données incorrectes inattendues

Les pipelines réussissent souvent pour la plupart des éléments d'entrée, mais échouent pour un petit sous-ensemble de l'entrée. Vous ne remarquerez peut-être pas ce problème lorsque vous exécuterez de petits tests, car ils ne testent qu'un sous-ensemble des entrées. Par défaut, Dataflow relance ces tâches ayant échoué quatre fois en mode de traitement par lot et un nombre illimité de fois en mode de traitement par flux. En mode de traitement par lot, une fois la limite de nouvelles tentatives atteinte, l'ensemble de la tâche échoue. En mode streaming, elle peut rester indéfiniment bloquée.

Dans de nombreuses tâches, vous pouvez exclure ces éléments défaillants du pipeline et effectuer le reste de la tâche à l'aide d'une file d'attente de lettres mortes (file d'attente de messages non traités). La file d'attente de messages non distribués transmet les enregistrements non distribués à un PCollection de sortie distinct, que vous pouvez gérer séparément de votre sortie principale. Cette configuration vous permet de concevoir une stratégie pour ces enregistrements. Par exemple, vous pouvez les écrire manuellement dans Pub/Sub, les inspecter et les nettoyer, puis réexécuter le traitement des enregistrements.

De nombreuses transformations Apache Beam sont compatibles avec les files d'attente de lettres mortes. En Java, vous pouvez y accéder avec un objet ErrorHandler. En Python, vous pouvez y accéder à l'aide de la méthode with_exception_handling. Certaines transformations définissent des files d'attente de messages non distribués de manière personnalisée. Pour en savoir plus, consultez la documentation de la transformation. Pour en savoir plus, consultez Utiliser des files d'attente de lettres mortes pour le traitement des erreurs.

Pour déterminer si votre tâche répond aux critères d'une file d'attente de messages non distribués, consultez la section Limites de ce document.

Limites de la file d'attente de lettres mortes

Dans les scénarios suivants, une file d'attente de messages non distribués peut ne pas être utile:

  • Défaillances du cycle de vie complet du worker ou de DoFn. Si le traitement échoue pour l'ensemble du nœud de calcul ou du lot, une file d'attente de messages non distribués ne peut pas détecter l'échec. Par exemple, si votre pipeline rencontre une exception de mémoire insuffisante (OOM), toutes les tâches actives sur la VM échouent et sont réessayées, sans rien envoyer à la file d'attente de messages non distribués.
  • Combines ou autres agrégations. Si votre pipeline effectue des calculs qui nécessitent que tous les éléments d'entrée soient présents et traités dans le résultat, soyez prudent lorsque vous utilisez une file d'attente de messages non distribués avant cette étape. L'utilisation d'une file d'attente de messages non distribués exclut une partie de vos données d'entrée du résultat. L'ajout d'une file d'attente de lettres mortes peut remplacer l'exactitude par la tolérance aux pannes.
  • Échecs sur le chemin de la file d'attente de lettres mortes. Si un élément échoue lors de son envoi à la destination de la file d'attente de messages non distribués, l'ensemble du pipeline peut échouer. Pour éviter cette erreur, simplifiez au maximum la logique de votre file d'attente de lettres mortes. Vous pouvez ajouter une étape d'attente (voir wait class) pour vous assurer que votre entrée principale se termine avant d'écrire les éléments de la file d'attente de messages non distribués. Cette configuration peut réduire les performances et retarder les signaux d'erreur de votre pipeline.
  • Éléments partiellement transformés. Si vous insérez une file d'attente de lettres mortes au milieu de votre pipeline, elle peut générer l'élément partiellement transformé et ne pas avoir accès à l'élément d'origine. Par conséquent, vous ne pouvez pas nettoyer l'élément et réexécuter le pipeline à son sujet. Vous devrez peut-être appliquer une logique différente pour mettre en corrélation la sortie de la file d'attente de messages non distribués avec l'élément d'origine, ou interpréter et traiter l'élément partiellement transformé. Cela peut également entraîner des résultats incohérents. Par exemple, si des éléments sont envoyés dans deux branches d'un pipeline, et que chaque branche envoie les éléments à l'origine d'une exception à une file d'attente de messages non distribués, un seul élément d'entrée peut passer dans l'une, l'autre, les deux ou aucune des branches.

Mettre en veille les enregistrements coûteux

Les pipelines peuvent cesser de répondre lors du traitement d'un petit sous-ensemble d'éléments plus coûteux ou qui rencontrent une limite qui entraîne une absence de réponse, comme un interblocage. Pour atténuer ce problème, certaines transformations vous permettent de définir un délai avant expiration et de faire échouer les éléments arrivés à expiration dans tous les DoFn de code utilisateur qui rencontrent ce problème. Par exemple, vous pouvez utiliser la méthode with_exception_handling de Python. Lorsque vous utilisez des délais avant expiration avec une file d'attente des lettres mortes, votre pipeline peut continuer à traiter les éléments valides et à progresser, et vous pouvez retraiter les éléments coûteux séparément. Cette configuration peut entraîner un coût en termes de performances.

Pour déterminer quelles opérations DoFn sont susceptibles de nécessiter un délai avant expiration, exécutez de petits tests avant de lancer votre pipeline complet.

Activer l'autoscaling vertical

Si vous ne savez pas de combien de mémoire votre tâche a besoin ou si vous pensez qu'elle risque de manquer de mémoire, activez l'autoscaling vertical. Cette fonctionnalité permet d'éviter les erreurs OOM lorsque les pipelines s'exécutent à plus grande échelle ou lorsqu'ils rencontrent des éléments exceptionnellement volumineux.

Étant donné que l'autoscaling vertical peut augmenter le coût de votre tâche et qu'il n'empêche pas tous les échecs liés à l'insuffisance de mémoire, vous devez toujours résoudre les problèmes de consommation excessive de mémoire. L'autoscaling vertical nécessite également Dataflow Prime, qui présente des limites supplémentaires et un modèle de facturation différent.

Solutions pour les pipelines sujets aux échecs

Certains pipelines sont particulièrement sujets aux erreurs. Bien qu'il soit préférable de résoudre la source de ces erreurs, envisagez les options suivantes pour réduire les coûts des défaillances.

Matérialiser les résultats intermédiaires

Les pipelines peuvent comporter une ou plusieurs transformations particulièrement coûteuses qui dominent le temps d'exécution du pipeline. Les échecs de pipeline après cette transformation peuvent être particulièrement nuisibles, car tout le travail déjà effectué est perdu. Pour éviter ce scénario, envisagez d'écrire des PCollections intermédiaires générés par des étapes coûteuses dans un collecteur tel que Cloud Storage. Cette configuration réduit le coût d'une défaillance. Vous devez comparer cet avantage au coût de l'écriture supplémentaire. Vous pouvez utiliser ce résultat matérié de l'une des manières suivantes:

  1. Divisez votre pipeline d'origine en deux pipelines: l'un qui écrit le résultat intermédiaire et l'autre qui le lit.
  2. En cas de défaillance du pipeline, lisez et aplatissez les résultats de votre source d'origine et de votre collection intermédiaire matérialisée.

Pour vous assurer que ces matérialisations sont écrites avant tout autre traitement, ajoutez une étape d'attente (voir wait class) avant toute étape de traitement ultérieure.