web-dev-qa-db-fra.com

Comprendre la prélecture des tâches de céleri

Je viens de découvrir l'option de configuration CELERYD_PREFETCH_MULTIPLIER ( documents ). La valeur par défaut est 4, mais (je crois) je veux que la prélecture soit la plus faible possible. Je l'ai mis à 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 cette prélecture est-elle une bonne idée? Je ne vois pas vraiment de raison à cela, sauf s'il y a beaucoup de latence entre la file d'attente de messages et les travailleurs (dans mon cas, ils s'exécutent actuellement sur le même hôte et, au pire, pourraient éventuellement s'exécuter sur différents hôtes dans les mêmes données centre). La documentation ne mentionne que les inconvénients, mais ne parvient pas à expliquer quels sont les avantages.

  2. Beaucoup de gens semblent mettre ce paramètre à 0, s'attendant à pouvoir désactiver la prélecture de cette façon (une hypothèse raisonnable à mon avis). Cependant, 0 signifie une prélecture illimitée. Pourquoi quelqu'un voudrait-il un prélecture illimité, cela n'élimine-t-il pas entièrement la simultanéité/asynchronicité pour laquelle vous avez introduit une file d'attente de tâches en premier lieu?

  3. Pourquoi la prélecture ne peut-elle pas être désactivée? Ce n'est peut-être pas une bonne idée de désactiver les performances dans la plupart des cas, mais y a-t-il une raison technique pour que cela ne soit pas possible? Ou n'est-il simplement pas mis en œuvre?

  4. Parfois, cette option est connectée à CELERY_ACKS_LATE. Par exemple. Roger Hu écrit "[…] souvent ce que [les utilisateurs] veulent vraiment, c'est qu'un travailleur réserve uniquement 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 connectées et pourquoi l'une n'est pas possible sans l'autre. Une autre mention de la connexion peut être trouvée ici . Quelqu'un peut-il expliquer pourquoi les deux options sont liées?

65
Henrik Heimbuerger
  1. La prélecture peut améliorer les performances. Les travailleurs n'ont pas besoin d'attendre le prochain message d'un courtier pour être traités. Communiquer avec un courtier une fois et traiter un grand nombre de messages améliore les performances. Obtenir un message d'un courtier (même local) coûte cher par rapport à l'accès à la mémoire locale. Les travailleurs sont également autorisés à accuser réception des messages par lots

  2. La prérécupération définie sur zéro signifie "pas de limite spécifique" plutôt qu'illimité

  3. La définition de la prélecture à 1 est documentée comme équivalant à la désactiver, mais ce n'est pas toujours le cas (voir https://stackoverflow.com/a/33357180/71522 )

  4. La prélecture permet d'accepter les messages par lots. CELERY_ACKS_LATE = True empêche la reconnaissance des messages lorsqu'ils atteignent un travailleur

23
mher

Vieille question, mais toujours en ajoutant ma réponse au cas où cela aiderait quelqu'un. Ma compréhension de certains tests initiaux était la même que celle de la réponse de David Wolever. Je viens de tester cela plus dans le céleri 3.1.19 et -Ofair fonctionne. Juste qu'il n'est pas destiné à désactiver la prélecture au niveau du nœud de travail. Cela continuera de se produire. En utilisant -Ofair a un effet différent qui est au niveau du travailleur de la piscine. En résumé, pour désactiver complètement la prélecture, procédez comme suit:

  1. Ensemble CELERYD_PREFETCH_MULTIPLIER = 1
  2. Ensemble CELERY_ACKS_LATE = True au niveau global ou au niveau de la tâche
  3. Utilisation -Ofair lors du démarrage des travailleurs
  4. Si vous définissez la simultanéité sur 1, l'étape 3 n'est pas nécessaire. Si vous souhaitez une concurrence plus élevée, l'étape 3 est essentielle pour éviter que les tâches ne soient sauvegardées dans un nœud qui pourrait être exécuté sur des tâches de longue durée.

Ajout de plus de détails:

J'ai constaté que le nœud de travail sera toujours prérécupéré par défaut. Vous pouvez uniquement contrôler le nombre de tâches qu'il prélève en utilisant CELERYD_PREFETCH_MULTIPLIER. S'il est défini sur 1, il prélèvera uniquement autant de tâches que le nombre de travailleurs de pool (simultanéité) dans le nœud. Donc, si vous aviez concurrency = n, le nombre maximal de tâches prélues par le nœud sera n.

Sans le -Ofair option, ce qui m'est arrivé, 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êteraient également de traiter les tâches déjà prélues par le nœud. En utilisant -Ofair, cela a changé. Même si l'un des travailleurs du nœud exécutait des tâches de longue durée, d'autres n'arrêtaient pas le traitement et continuaient à traiter les tâches prélues par le nœud. Je vois donc deux niveaux de prélecture. Un au niveau du nœud de travail. L'autre au niveau du travailleur individuel. En utilisant -Ofair pour moi semblait le désactiver au niveau des travailleurs.

Comment est ACKS_LATE en relation? ACKS_LATE = True signifie que la tâche ne sera reconnue que lorsque la tâche réussira. Sinon, je suppose que cela arriverait quand il serait reçu par un travailleur. En cas de prélecture, la tâche est d'abord reçue par le travailleur (confirmée à partir des journaux) mais sera exécutée plus tard. Je viens de réaliser que les messages prélus apparaissent sous "messages non reconnus" dans rabbitmq. Je ne suis donc pas sûr que le paramétrer sur True soit absolument nécessaire. De toute façon, nos tâches avaient été définies de cette façon (accusé de réception tardif) pour d'autres raisons.

21
ksrini

Juste un avertissement: à partir de mes tests avec le courtier redis + Celery 3.1.15, tous les conseils que j'ai lus concernant la désactivation de la prélecture CELERYD_PREFETCH_MULTIPLIER = 1 Sont manifestement faux.

Pour le démontrer:

  1. Définissez CELERYD_PREFETCH_MULTIPLIER = 1
  2. Mettez en file d'attente 5 tâches qui prendront chacune quelques secondes (ex, time.sleep(5))
  3. Commencez à regarder la longueur de la file d'attente des tâches dans Redis: watch redis-cli -c llen default

  4. Démarrer celery worker -c 1

  5. Notez que la longueur de la file d'attente dans Redis passera immédiatement de 5 À 3

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

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

À moins de modifier le code source, je n'ai trouvé aucune méthode pour désactiver entièrement la prélecture.

14
David Wolever

Je ne peux pas commenter les réponses de David Wolever, car mon stackcred n'est pas assez élevé. J'ai donc encadré mon commentaire comme une réponse car j'aimerais partager mon expérience avec Celery 3.1.18 et un courtier Mongodb. J'ai réussi à arrêter la prélecture avec les éléments suivants:

  1. ajouter CELERYD_PREFETCH_MULTIPLIER = 1 à la config céleri
  2. ajouter CELERY_ACKS_LATE = True à la config céleri
  3. Démarrez le céleri avec les options: --concurrency=1 -Ofair

En laissant CELERY_ACKS_LATE à la valeur par défaut, le travailleur effectue toujours une prélecture. Tout comme l'OP, je ne saisis pas complètement le lien entre la prélecture et les accusés de réception tardifs. Je comprends ce que David dit "CELERY_ACKS_LATE = True empêche de reconnaître les messages lorsqu'ils atteignent un travailleur", mais je n'arrive pas à comprendre pourquoi les accusés de réception tardifs seraient incompatibles avec la prélecture. En théorie, une prélecture permettrait toujours d'acquitter tard à droite - même si elle n'est pas codée comme telle dans le céleri?

9