Pourquoi ma tâche AWS Glue ETL échoue-t-elle avec l'erreur « Conteneur tué par YARN pour dépassement des limites de mémoire » ?

Date de la dernière mise à jour : 21/07/2021

Ma tâche Extract-transform-load (ETL) AWS Glue échoue avec l'erreur « Conteneur tué par YARN pour dépassement des limites de mémoire ».

Brève description

Les causes les plus courantes de cette erreur sont les suivantes :

  • Opérations gourmandes en mémoire, notamment la jonction de grandes tables ou le traitement de jeux de données avec une distorsion dans la distribution de valeurs de colonnes spécifiques, dépassant le seuil de mémoire du cluster Spark sous-jacent
  • Partitions Fat de données qui consomment plus que la mémoire affectée à l'exécuteur respectif
  • Fichiers volumineux et indivisibles, ce qui entraîne des partitions en mémoire volumineuses

Résolution

Utilisez une ou plusieurs des options de solution suivantes pour résoudre cette erreur :

  • Mettez à niveau le type de travailleur de G1.x vers G2.x doté de configurations de mémoire supérieures. Pour plus d'informations sur les spécifications des types de travail, reportez-vous à la section Type de travailleur dans Définition des propriétés de tâche pour les tâches Spark. Vous pouvez également consulter le tableau suivant pour obtenir des informations sur les spécifications du type de travailleur :
Standard spark.executor.memory : 5 g
spark.driver.memory : 5 g
spark.executor.cores : 4
G1.x spark.executor.memory : 10g
spark.driver.memory : 10g
spark.executor.cores : 8
G2.x spark.executor.memory : 20g
spark.driver.memory : 20g
spark.executor.cores : 16
  • Si l'erreur persiste après la mise à niveau du type de travailleur, augmentez le nombre d'exécuteurs de la tâche. Chaque exécuteur possède un certain nombre de cœurs. Ce numéro détermine le nombre de partitions pouvant être traitées par l'exécuteur. Les configurations Spark pour les unités de traitement des données (DPU) sont définies en fonction du type de travailleur.
  • Assurez-vous que les données sont correctement parallélisées afin que les exécuteurs puissent être utilisés uniformément avant toute opération aléatoire comme les jointures. Vous pouvez repartitionner les données entre tous les exécuteurs. Vous pouvez le faire en incluant les commandes suivantes pour AWS Glue DynamicFrame et Spark DataFrame dans votre tâche ETL, respectivement.
dynamicFrame.repartition(totalNumberOfExecutorCores)
dataframe.repartition(totalNumberOfExecutorCores)
  • L'utilisation des marque-pages de tâche permet de traiter uniquement les fichiers récemment écrits par la tâche AWS Glue. Cela réduit la quantité de fichiers traités par la tâche AWS Glue et atténue les problèmes de mémoire. Les marque-pages stockent les métadonnées relatives aux fichiers traités lors de l'exécution précédente. Au cours de l'exécution suivante, la tâche compare l'horodatage, puis décide de traiter à nouveau ces fichiers. Pour plus d'informations, consultez Suivi des données traitées à l'aide de marque-pages de tâche.
  • Lorsque vous vous connectez à une table JDBC, Spark n'ouvre qu'une seule connexion simultanée par défaut. Le pilote essaie de télécharger la table entière en une seule fois dans un seul exécuteur Spark. Cela peut prendre plus de temps et même entraîner des erreurs de type mémoire insuffisante pour l'exécuteur. Vous pouvez plutôt définir des propriétés spécifiques de votre table JDBC pour demander à AWS Glue de lire les données en parallèle via DynamicFrame. Pour plus d'informations, consultez Lecture des tables JDBC en parallèle. Vous pouvez également faire des lectures en parallèle depuis JDBC via Spark DataFrame. Pour plus d'informations, consultez Lectures en parallèle Spark DataFrame à partir de JDBC et examinez les propriétés, en particulier partitionColumn,lowerBound, upperBound et numPartitions.
  • Évitez d'utiliser des fonctions définies par l'utilisateur dans votre tâche ETL, en particulier lorsque vous combinez le code Python/Scala aux fonctions et méthodes de Spark. Par exemple, évitez d'utiliser df.count () de Spark pour vérifier les DataFrames vides dans les instructions if/else ou pour les boucles. Utilisez plutôt une fonction plus performante comme df.schema () ou df.rdd.isEmpty ().
  • Testez la tâche AWS Glue sur un point de terminaison de développement et optimisez le code ETL en conséquence.
  • Si aucune des options de solution précédentes ne fonctionne, partitionnez les données d'entrée ou divisez-les en blocs. Ensuite, exécutez plusieurs tâches AWS Glue ETL au lieu d'exécuter une seule tâche importante. Pour plus d'informations, consultez Partitionnement de l'application avec exécution limitée.