92 votes

Comprendre les tâches de celery prefetching

Je viens de découvrir l'option de configuration CELERYD_PREFETCH_MULTIPLIER ( docs ). La valeur par défaut est 4, mais (je crois) que je veux que le prefetching soit désactivé ou aussi bas que possible. Je l'ai réglé sur 1 maintenant, ce qui est assez proche de ce que je recherche, mais il y a encore des choses que je ne comprends pas :

  1. Pourquoi ce prefetching est-il une bonne idée ? Je n'en vois pas vraiment la raison, à moins qu'il n'y ait beaucoup de latence entre la file d'attente des messages et les travailleurs (dans mon cas, ils fonctionnent actuellement sur le même hôte et, au pire, ils pourraient éventuellement fonctionner sur des hôtes différents dans le même centre de données). La documentation ne mentionne que les inconvénients, mais n'explique pas quels sont les avantages.

  2. Beaucoup de gens semblent mettre cette valeur à 0, s'attendant à pouvoir désactiver le prefetching de cette façon (une supposition raisonnable à mon avis). Cependant, 0 signifie que le prefetching est illimité. Pourquoi quelqu'un voudrait-il un prefetching illimité, cela n'élimine-t-il pas entièrement la concurrence/asynchronicité pour laquelle vous avez introduit une file d'attente de tâches en premier lieu ?

  3. Pourquoi ne peut-on pas désactiver le préfixe ? Ce n'est peut-être pas une bonne idée pour les performances de la désactiver dans la plupart des cas, mais y a-t-il une raison technique pour laquelle cela n'est pas possible ? Ou n'est-elle tout simplement pas implémentée ?

  4. Parfois, cette option est liée à CELERY_ACKS_LATE . Par exemple. Roger Hu écrit "Souvent, ce que [les utilisateurs] veulent vraiment, c'est qu'un travailleur ne réserve qu'autant de tâches qu'il y a de processus enfants. Mais cela n'est pas possible sans activer les accusés de réception tardifs [ ]" Je ne comprends pas comment ces deux options sont liées et pourquoi l'une n'est pas possible sans l'autre. Une autre mention de la connexion peut être trouvée aquí . Quelqu'un peut-il expliquer pourquoi les deux options sont liées ?

39voto

0x00mh Points 2696
  1. Le préemption peut améliorer les performances. Les travailleurs n'ont pas besoin d'attendre le prochain message d'un courtier pour le traiter. Communiquer une fois avec un courtier et traiter un grand nombre de messages permet de gagner en performance. Obtenir un message d'un courtier (même d'un courtier local) est coûteux par rapport à l'accès à la mémoire locale. Les travailleurs sont également autorisés à accuser réception des messages par lots.

  2. Un préfixe fixé à zéro signifie "aucune limite spécifique" plutôt qu'illimité.

  3. Il est documenté que le fait de régler la préextraction sur 1 équivaut à la désactiver, mais ce n'est pas toujours le cas (cf. https://stackoverflow.com/a/33357180/71522 )

  4. Le préemption permet de recevoir des messages par lots. CELERY_ACKS_LATE=True empêche d'accuser réception des messages lorsqu'ils parviennent à un travailleur.

29voto

ksrini Points 185

Vieille question, mais j'ajoute quand même ma réponse au cas où elle aiderait quelqu'un. J'ai compris que les tests initiaux étaient identiques à ceux de la réponse de David Wolever. Je viens juste de tester ceci dans celery 3.1.19 et -Ofair fonctionne. Juste qu'il n'est pas censé désactiver le prefetch au niveau du nœud de travail. Cela continuera à se produire. Utilisation de -Ofair a un effet différent qui se situe au niveau des travailleurs du pool. En résumé, pour désactiver complètement le prefetch, faites ceci :

  1. Définir CELERYD_PREFETCH_MULTIPLIER = 1
  2. Définir CELERY_ACKS_LATE = True au niveau global ou au niveau des tâches
  3. Utilisez -Ofair tout en démarrant les travailleurs
  4. Si vous définissez la concurrence à 1, l'étape 3 n'est pas nécessaire. Si vous souhaitez une plus élevée, l'étape 3 est essentielle pour éviter que les tâches ne soient sauvegardées dans un nœud qui pourrait exécuter des tâches longues.

J'ajoute quelques détails supplémentaires :

J'ai découvert que le nœud de travail va toujours prélever par défaut. Vous pouvez seulement contrôler le nombre de tâches qu'il prélivre en utilisant la commande CELERYD_PREFETCH_MULTIPLIER . S'il est défini à 1, il ne prélèvera que le nombre de tâches correspondant au nombre de travailleurs du pool (concurrence) dans le nœud. Ainsi, si vous avez une concurrence = n, le nombre maximum de tâches préextraites par le nœud sera de n.

Sans le -Ofair Ce qui s'est passé pour moi, c'est que si l'un des processus de travail du pool exécutait une tâche de longue durée, les autres travailleurs du nœud arrêtaient également de traiter les tâches déjà préenregistrées par le nœud. En utilisant -Ofair ça a changé. Même si l'un des travailleurs du nœud exécutait une tâche en cours depuis longtemps, les autres ne s'arrêtaient pas et continuaient à traiter les tâches préenregistrées par le nœud. Je vois donc deux niveaux de préemption. L'un au niveau du nœud de travailleurs. L'autre au niveau du travailleur individuel. Utilisation de -Ofair pour moi semblait le désactiver au niveau du travailleur.

Comment ACKS_LATE liés ? ACKS_LATE = True signifie que la tâche ne sera acquittée que si elle réussit. Sinon, je suppose que cela se produirait lorsqu'elle est reçue par un travailleur. Dans le cas de la préextraction, la tâche est d'abord reçue par le travailleur (confirmé par les journaux) mais sera exécutée plus tard. . Je viens de me rendre compte que les messages préenregistrés apparaissent sous la rubrique "messages non acquittés" dans rabbitmq. Donc je ne suis pas sûr que le fait de le mettre sur True est absolument nécessaire. Nous avons de toute façon configuré nos tâches de cette façon (ack tardif) pour d'autres raisons.

21voto

David Wolever Points 34304

Juste un avertissement : lors de mes tests avec le courtier redis + Celery 3.1.15, tous les conseils que j'ai pu lire concernant CELERYD_PREFETCH_MULTIPLIER = 1 désactiver le prefetching est démonstrativement faux.

Pour le démontrer :

  1. Définir CELERYD_PREFETCH_MULTIPLIER = 1

  2. Mettez en file d'attente 5 tâches qui prendront chacune quelques secondes (ex, time.sleep(5) )

  3. Commencez à surveiller la longueur de la file d'attente des tâches dans Redis : watch redis-cli -c llen default

  4. Début celery worker -c 1

  5. Notez que la longueur de la file d'attente dans Redis va immédiatement passer de 5 à 3

CELERYD_PREFETCH_MULTIPLIER = 1 n'empêche pas la préextraction il limite simplement la préextraction à une tâche par file d'attente.

-Ofair , malgré ce que dit la documentation également n'empêche pas la préextraction .

À moins de modifier le code source, je n'ai pas trouvé de méthode permettant de désactiver complètement le prefetching.

13voto

Je ne peux pas commenter les réponses de David Wolever, car mon stackcred n'est pas assez élevé. J'ai donc formulé mon commentaire comme une réponse, car j'aimerais partager mon expérience avec Celery 3.1.18 et un broker Mongodb. J'ai réussi à arrêter le prefetching avec ce qui suit :

  1. ajouter CELERYD_PREFETCH_MULTIPLIER = 1 à la configuration du céleri
  2. ajouter CELERY_ACKS_LATE = True à la configuration du céleri
  3. Commencez le travailleur du céleri avec des options : --concurrency=1 -Ofair

En laissant CELERY_ACKS_LATE à la valeur par défaut, le travailleur préfigure toujours. Tout comme l'OP, je ne saisis pas complètement le lien entre le prefetching et les late acks. Je comprends ce que David dit "CELERY_ACKS_LATE=True empêche d'acquitter les messages lorsqu'ils arrivent à un worker", mais je ne comprends pas pourquoi les acks tardifs seraient incompatibles avec le prefetch. En théorie, un prefetch permettrait toujours d'acquitter les messages tardivement - même si ce n'est pas codé comme tel dans celery ?

1voto

gCoh Points 625

J'ai vécu une expérience un peu différente avec SQS comme courtier.

La configuration était :

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

Après l'échec de la tâche (exception levée), le travailleur est devenu indisponible car le message n'a pas été accepté, tant dans la file d'attente locale que distante.

La solution qui a fait que les travailleurs ont continué à consommer du travail a été de fixer

CELERYD_PREFETCH_MULTIPLIER = 0

Je ne peux que supposer que acks_late n'a pas été pris en considération lors de l'écriture du transport SQS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X