Bonnes pratiques en matière de nouvelles tentatives d'exécution et de points de contrôle

Des tâches individuelles, voire des exécutions de tâches, peuvent échouer pour diverses raisons. Cette page contient les bonnes pratiques à suivre pour gérer ces échecs, centrées sur les redémarrages de tâches et la création de points de contrôle de tâche.

Utiliser les nouvelles tentatives de tâche

Les tâches de job individuelles peuvent échouer pour diverses raisons, y compris des problèmes liés aux dépendances d'application, aux quotas ou même aux événements système internes. Ces problèmes sont souvent temporaires et la tâche aboutit après une nouvelle tentative.

Par défaut, chaque tâche fait automatiquement l'objet de trois tentatives au maximum. Cela permet de s'assurer qu'un job s'exécute jusqu'à son terme, même s'il rencontre des échecs de tâches temporaires. Vous pouvez également personnaliser le nombre maximal de nouvelles tentatives. Toutefois, si vous modifiez la valeur par défaut, vous devez spécifier au moins une tentative.

Planifier les redémarrages des tâches

Rendez vos tâches idempotentes, de sorte qu'un redémarrage de tâche n'entraîne pas de sortie corrompue ou en double. Autrement dit, écrivez une logique reproductible qui présente le même comportement pour un ensemble d'entrées donné, quel que soit le nombre de répétitions ou d'exécution.

Écrivez votre sortie dans un emplacement différent de celui des données d'entrée, en laissant les données d'entrée intactes. Ainsi, si la tâche s'exécute à nouveau, elle peut répéter le processus depuis le début et obtenir le même résultat.

Évitez de dupliquer les données de sortie en réutilisant le même identifiant unique ou en vérifiant si la sortie existe déjà. Les données en double représentent une corruption des données au niveau de la collection.

Utiliser la création de points de contrôle

Dans la mesure du possible, contrôlez vos tâches de sorte que, si une tâche redémarre après un échec, elle peut reprendre là où elle s'était arrêtée, au lieu de reprendre du début. Cette pratique permet d'accélérer vos tâches et de minimiser les coûts inutiles.

Écrivez régulièrement des résultats partiels et une indication de la progression dans un emplacement de stockage persistant, tel que Cloud Storage ou une base de données. Au démarrage de la tâche, recherchez les résultats partiels au démarrage. Si des résultats partiels sont trouvés, commencez le traitement là où ils se sont arrêtés.

Si votre tâche ne se prête pas à la création de points de contrôle, envisagez de la diviser en plus petits fragments et d'exécuter un plus grand nombre de tâches.

Exemple de point de contrôle 1: calculer Pi

Si une tâche exécute un algorithme récursif, tel que le calcul de pi sur plusieurs décimales, et utilise le parallélisme défini sur une valeur de 1 :

  • Écrivez votre progression dans un objet Cloud Storage pi-progress.txt toutes les 10 minutes ou selon votre tolérance à la perte de travail.
  • Lorsqu'une tâche démarre, interrogez l'objet pi-progress.txt et chargez la valeur comme point de départ. Utilisez cette valeur comme entrée initiale de votre fonction.
  • Écrivez votre résultat final dans Cloud Storage en tant qu'objet nommé pi-complete.txt pour éviter la duplication via une exécution parallèle ou répétée, ou pi-complete-DATE.txt pour différencier par date d'achèvement.

Exemple de point de contrôle 2 : traitement de 10 000 enregistrements depuis Cloud SQL

Si vous avez une tâche de traitement de 10 000 enregistrements dans une base de données relationnelle telle que Cloud SQL :

  • Récupérez les enregistrements à traiter avec une requête SQL telle que SELECT * FROM example_table LIMIT 10000.
  • Écrivez les enregistrements mis à jour par lots de 100 afin que les tâches de traitement importantes ne soient pas perdues lors d'une interruption.
  • Lorsque les enregistrements sont écrits, notez ceux qui ont été traités. Vous pouvez ajouter une colonne booléenne traitée à la table, qui n'est définie sur 1 que si le traitement est confirmé.
  • Lorsqu'une tâche démarre, la requête utilisée pour récupérer les éléments à traiter doit ajouter la condition traitée = 0.
  • Outre les nouvelles tentatives, cette technique permet également de diviser le travail en tâches plus petites, par exemple en modifiant votre requête pour sélectionner 100 enregistrements à la fois : LIMIT 100 OFFSET $CLOUD_RUN_TASK_INDEX*100, et en exécutant 100 tâches pour traiter l'ensemble des 10 000 enregistrements. CLOUD_RUN_TASK_INDEX est une variable d'environnement intégrée au conteneur qui exécute des tâches Cloud Run.

En utilisant tous ces éléments ensemble, la requête finale devrait ressembler à ceci : SELECT * FROM example_table WHERE processed = 0 LIMIT 100 OFFSET $CLOUD_RUN_TASK_INDEX*100

Étapes suivantes