10
votes

Calendrier de la tâche de céleri (céleri, django et rabbbitmq)

Je veux avoir une tâche qui s'exécutera toutes les 5 minutes, mais elle attendra la dernière exécution de terminer, puis de commencer à compter ces 5 minutes. (De cette façon, je peux aussi être sûr qu'il n'y a qu'une seule tâche en cours d'exécution), le moyen le plus simple que j'ai trouvé est d'exécuter django application gérer.py shell et d'exécuter ceci: xxx

mais pour chaque tâche que Je veux exécuter de cette façon, je dois courir sa propre shell, y a-t-il un moyen facile de le faire? Peut-être du king Custom Ot Django Celery Scheduler?


0 commentaires

6 Réponses :


12
votes

Tout ce dont vous avez besoin est spécifié dans la tâche de la sorcière de céleri que vous souhaitez exécuter périodiquement et avec quel intervalle.

Exemple: exécutez la tâche Tâches.Ajouter toutes les 30 secondes P>

CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler"


5 commentaires

Le problème avec ceci est qu'il n'attendra pas la tâche à terminer, mais n'enverra qu'une autre tâche quand il est temps (toutes les 30 secondes). Ou peut-être que je me trompe?


Merci de conseils, mais je pense que je veux quelque chose d'autre - je veux créer un emploi, l'envoyer à l'exécution et créer un autre emploi uniquement lorsque l'exécution de la précédente est terminée. Je ne veux pas créer d'emplois jusqu'à ce que je sache que le précédent est terminé. Je veux que la tâche ait un comportement synchrone (non asynchrone)


L'objectif global est de faire fonctionner une tâche pour laquelle je ne peux pas dire combien de temps il faudra et quand il sera fini, attendez un peu de temps et recommencez. De plus, je dois être sûr de ne pas être exécuté 2 ou plus de fois simultanément par différents threads de travailleurs, et que je n'ai pas besoin d'écrire mon propre code de programme pour le faire.


Si vous souhaitez vous assurer que une tâche ne démarre qu'après la fin du dernier, utilisez MemCached (ou Django cache) pour créer un verrou sur le type de tâche ou la ressource dans ladite tâche. C'est facile et évolutif à faire.


@MAUROROCCO Ce n'est pas vrai, au moins à partir de 3.0.12, CELERY Beat créera certainement des tâches qui se chevauchent.



4
votes

Pour développer le message de @ Maurorocco, de http: // docs.eleyproject.org/fr/v2.2.4/userguide/periodic-tasks.html

Utilisation d'un TimerEDelta pour la planification signifie que la tâche sera exécutée 30 secondes après la démarrage de célerybat, puis toutes les 30 secondes après la dernière course. Un horaire semblable à Crontab existe également, voir la section sur les horaires de crontab.

Donc, cela atteindra effectivement l'objectif que vous voulez.


2 commentaires

Désolé, sur la question, mais si la tâche prend 20 secondes pour compléter, fonctionnera-t-elle à 0:30 (1 ST), fini à 0:50, puis commencer à 1:20 (c'est ce que je veux vraiment)


Si vous souhaitez que la tâche fonctionne toutes les 30 secondes de manière indépendante de la durée que vous devez utiliser un horaire de crontab, mais rappelez-vous que cette tâche est ajoutée à la file d'attente de céleri et s'il y a d'autres tâches dans l'exécution / la file d'attente, vous ne savez pas que votre tâche commence au moment donné.



16
votes

Vous pouvez être intéressé par cette méthode plus simple qui ne nécessite aucune modification d'un céleri Conf. XXX


2 commentaires

J'ai eu une erreur "céleri" objet n'a aucun attribut 'décorateurs'. Aucune idée à ce sujet? J'ai écrit @ célery.decorators.periodic_task (Run_Every = DateTime.Timeedelt A (minutes = 5)) au-dessus de ma tâche.


La dernière version de célery n'a pas ce décorateur. Vous devrez simplement utiliser les instructions ici: Docs.CeleyProject.org /en/latest/userguide/periodic-tasks.ht ml



2
votes

à cause de célery.decorators obsolètes, vous pouvez utiliser périodique_task décorator comme celui-ci:

from celery.task.base import periodic_task
from django.utils.timezone import timedelta

@periodic_task(run_every=timedelta(seconds=5))
def my_background_process():
    # insert code


0 commentaires

17
votes

wow c'est incroyable comment personne ne comprend la question de cette personne. Ils ne demandent pas de tâches de fonctionnement périodiquement, mais comment s'assurer que le céleri ne gère pas deux instances de la même tâche simultanément. Je ne pense pas qu'il y ait un moyen de le faire avec le céleri directement, mais ce que vous pouvez faire est d'avoir l'une des tâches d'acquérir une verroue à droite lorsqu'elle commence et si elle échoue, pour réessayer dans quelques secondes (en utilisant une nouvelle tentative) . La tâche relâcherait le droit de verrouillage avant son retour; Vous pouvez faire expirer le verrouillage automatique après quelques minutes si elle se bloque jamais.

Pour le verrou, vous pouvez probablement utiliser votre base de données ou quelque chose comme Redis.


1 commentaires

+1. La seule personne à résoudre le problème d'instance unique! Détails sur la manière de mettre en place un verrou si vous utilisez une base de données Django, vous trouverez ici: Stackoverflow.com/Questtions/4095940/...



0
votes

Ajoutez cette tâche à une file d'attente distincte, puis utilisez un travailleur distinct pour cette file d'attente avec l'option de concurrence définie sur 1.


0 commentaires