J'ai 2 types de tâches: Type1 - Quelques petites tâches hautement prioritaires. Type2 - Beaucoup de tâches lourdes avec une priorité plus basse.
Initialement, j'avais une configuration simple avec un routage par défaut, aucune clé de routage n'a été utilisée. Ce n'était pas suffisant - parfois, tous les travailleurs étaient occupés par des tâches de type 2, ce qui a retardé la tâche 1. J'ai ajouté des clés de routage:
CELERY_DEFAULT_QUEUE = "default"
CELERY_QUEUES = {
"default": {
"binding_key": "task.#",
},
"highs": {
"binding_key": "starter.#",
},
}
CELERY_DEFAULT_EXCHANGE = "tasks"
CELERY_DEFAULT_EXCHANGE_TYPE = "topic"
CELERY_DEFAULT_ROUTING_KEY = "task.default"
CELERY_ROUTES = {
"search.starter.start": {
"queue": "highs",
"routing_key": "starter.starter",
},
}
Alors maintenant, j'ai 2 files d'attente - avec des tâches de priorité haute et basse.
Le problème est - comment démarrer 2 celeryd avec différents paramètres de simultanéité?
Auparavant, le céleri était utilisé en mode démon (selon à cela ), donc seul le début de /etc/init.d/celeryd start
était requis, mais maintenant je dois exécuter 2 célerids différents avec des files d'attente et des accès concurrents différents. Comment puis-je le faire?
Il semble que la réponse - céleri-multi - n’est actuellement pas bien documentée.
Ce dont j'avais besoin peut être fait avec la commande suivante:
celeryd-multi start 2 -Q:1 default -Q:2 starters -c:1 5 -c:2 3 --loglevel=INFO --pidfile=/var/run/celery/${USER}%n.pid --logfile=/var/log/celeryd.${USER}%n.log
Ce que nous faisons, c’est démarrer 2 travailleurs qui écoutent différentes files d’attente (-Q: 1 par défaut, Q: 2 est les démarreurs) avec des concédences différentes -c: 1 5 -c: 2 3
Sur la base de la réponse ci-dessus, j'ai formulé le fichier suivant/etc/default/celeryd (basé à l'origine sur la configuration décrite dans la documentation ici: http://ask.github.com/celery/cookbook/daemonizing.html ) qui fonctionne pour l'exécution de deux travailleurs de céleri sur le même ordinateur, chaque travailleur desservant une file d'attente différente (dans ce cas, les noms de la file d'attente sont "par défaut" et "important").
Fondamentalement, cette réponse est simplement une extension de la réponse précédente en ce sens qu'elle montre simplement comment faire la même chose, mais pour le céleri en mode démon. Veuillez noter que nous utilisons Django-céleri ici:
CELERYD_NODES="w1 w2"
# Where to chdir at start.
CELERYD_CHDIR="/home/peedee/projects/myproject/myproject"
# Python interpreter from environment.
#ENV_PYTHON="$CELERYD_CHDIR/env/bin/python"
ENV_PYTHON="/home/peedee/projects/myproject/myproject-env/bin/python"
# How to call "manage.py celeryd_multi"
CELERYD_MULTI="$ENV_PYTHON $CELERYD_CHDIR/manage.py celeryd_multi"
# How to call "manage.py celeryctl"
CELERYCTL="$ENV_PYTHON $CELERYD_CHDIR/manage.py celeryctl"
# Extra arguments to celeryd
# Longest task: 10 hrs (as of writing this, the UpdateQuanitites task takes 5.5 hrs)
CELERYD_OPTS="-Q:w1 default -c:w1 2 -Q:w2 important -c:w2 2 --time-limit=36000 -E"
# Name of the celery config module.
CELERY_CONFIG_MODULE="celeryconfig"
# %n will be replaced with the nodename.
CELERYD_LOG_FILE="/var/log/celery/celeryd.log"
CELERYD_PID_FILE="/var/run/celery/%n.pid"
# Name of the projects settings module.
export Django_SETTINGS_MODULE="settings"
# celerycam configuration
CELERYEV_CAM="djcelery.snapshot.Camera"
CELERYEV="$ENV_PYTHON $CELERYD_CHDIR/manage.py celerycam"
CELERYEV_LOG_FILE="/var/log/celery/celerycam.log"
# Where to chdir at start.
CELERYBEAT_CHDIR="/home/peedee/projects/cottonon/cottonon"
# Path to celerybeat
CELERYBEAT="$ENV_PYTHON $CELERYBEAT_CHDIR/manage.py celerybeat"
# Extra arguments to celerybeat. This is a file that will get
# created for scheduled tasks. It's generated automatically
# when Celerybeat starts.
CELERYBEAT_OPTS="--schedule=/var/run/celerybeat-schedule"
# Log level. Can be one of DEBUG, INFO, WARNING, ERROR or CRITICAL.
CELERYBEAT_LOG_LEVEL="INFO"
# Log file locations
CELERYBEAT_LOGFILE="/var/log/celerybeat.log"
CELERYBEAT_PIDFILE="/var/run/celerybeat.pid"
Une autre alternative consiste à attribuer un nom unique au processus de travail en utilisant l’argument -n
.
J'ai deux applications Pyramid s'exécutant sur le même matériel physique, chacune avec sa propre instance de céleri (dans leurs propres virtualenvs).
Superviseur les contrôle tous les deux, les deux avec un fichier supervisord.conf unique.
app1:
[program:celery]
autorestart=true
command=%(here)s/../bin/celery worker -n ${Host}.app1--app=app1.queue -l debug
directory=%(here)s
[2013-12-27 10:36:24,084: WARNING/MainProcess] [email protected] ready.
app2:
[program:celery]
autorestart=true
command=%(here)s/../bin/celery worker -n ${Host}.app2 --app=app2.queue -l debug
directory=%(here)s
[2013-12-27 10:35:20,037: WARNING/MainProcess] [email protected] ready.
Une mise à jour:
Dans Celery 4.x, ci-dessous fonctionnerait correctement:
celery multi start 2 -Q:1 celery -Q:2 starters -A $proj_name
Ou si vous souhaitez désigner le nom de l'instance, vous pouvez:
celery multi start name1 name2 -Q:name1 celery -Q:name2 queue_name -A $proj_name
Cependant, je trouve que cela n’imprimerait pas les journaux de détails à l’écran si nous utilisions celery multi
car il semble qu’un simple raccourci de script permette de démarrer ces instances.
Je suppose que cela fonctionnerait également si nous démarrions ces instances une à une manuellement en leur attribuant des noms de nœud différents, mais -A
le même $proj_name
bien que ce soit un peu une perte de temps.
Au fait, selon le document officiel , vous pourriez tuer tous les céleri-raves simplement en:
ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill -9