La configurazione illustrata qui usa django_celery che fornisce l’app djcelery ed è la soluzione più semplice. django-celery in aggiunta ha anche altre interessanti funzionalità per i crontab.
In install_requires di setup.py aggiungere:
install_requires = [
...
'jmb.async',
'django-celery'
]
in settings.py (per noi base.py):
INSTALLED_APPS = (
....
'jmb.async',
'kombu.transport.django',
'djcelery',
)
e poi mettere in settings.__init__.py dopo ogni altra cosa:
import jmb.async.celeryapp
In particolare questo crea l’app celery usando i default per BROKER_URL e CELERY_RESULT_BACKEND definiti nei settings
ricordarsi di lanciare nella shell:
dj syncdb && dj migrate
vedi qui come configurare async per dev o per prod Gestione start / stop /reload per avviare il servizio di celery lanciare:
dj celery worker -l info
Che è un comando del pacchetto django_celery
Note
la documentazione di celery suggerisce di mettere la creazione della app di celery in proj.__init__ ma questo implica avere già letto i settings ed a me sembra che ci sia un errore nella sequenza di inizializzazione per la particolare configurazione scelta da noi (in cui ogni app nell’__init__ scrive i proprio settings di default nei settings ufficiali).
Per questo importiamo il modulo che crea l’app celery come ultima azione nei settings (che per noi sono una cartella quindi in settings.__init__.py)
Se sei in modalità DEBUG = True, su /admin/async/task/ trovi una azione predefinita che crea un task che conta 40 secondi. Puoi creare a mano un task in modo da potere eseguire l’azione e vedere la progress bar in azione.
Complimenti! ora puoi iniziare ad aggiungere un task utile seguendo le istruzioni
In produzione è preferito l’uso di rabbitMQ facilmente ottenibile semplicemente impostando poche variabili.
http://celery.readthedocs.org/en/latest/getting-started/first-steps-with-celery.html#rabbitmq
http://celery.readthedocs.org/en/latest/getting-started/brokers/rabbitmq.html
http://celery.readthedocs.org/en/latest/configuration.html#amqp-backend-settings
esempio di configurazione sostituire ai parametri di dev questi nei settings.py:
BROKER_URL = 'amqp://'
CELERY_RESULT_BACKEND = 'amqp://'
CELERY_RESULT_BACKEND = 'amqp'
CELERY_TASK_RESULT_EXPIRES = 18000 # 5 hours.
Nel tentativo di fissare un nostro std, usiamo come user il nick usato per uwsgi e come vhost nick_producion|nick_pre:
CELERY_USER=thux PASS=mypass VHOST=thux_production
apt-get install rabbitmq-server
rabbitmqctl add_user $CELERY_USER $PASS
rabbitmqctl add_vhost $VHOST
rabbitmqctl set_permissions -p $VHOST $CELERY_USER ".*" ".*" ".*"
echo BROKER_URL = "amqp://$CELERY_USER:$PASS@localhost:5672/$VHOST"
start/stop/reload dei processi uwsgi sono gestiti da noi con dj:
dj start
dj reload
dj restart
dj stop [ -9 ]
dj ps
All’interno della configurazione di uwsgi, c’è una direttiva chiamata attach-daemon2 che avvia celery se non è già avviato ed invia un segnale TERM (15) quando si fa reload del processo uwsgi.
In uwsgi 2.0.7 non sembra funzionare invece lo stop per cui ho fatto in modo che sia dj stesso ad emettere in kill -3 (o kill -9) del processo. Questo è basato su una precisa convenzione che il processo scriva nel file /var/run/uwsgi/$NICK-celery.pid il suo pid
La documentazione ufficiale di celery dichiara che possono essere usati questi segnali:
TERM: | Warm shutdown, wait for tasks to complete (kill -15) |
---|---|
QUIT: | Cold shutdown, terminate ASAP (kill -3) |
KILL: | Solo quando un processo non si riesca a chiudere in altro modo. Questo può essere fatto con dj stop -9. Verificare con dj ps che effettivamente sia andato a buon fine. |
Celery legge le variabili direttamente dai settings di Diango. Gli stati ammessi sono definiti da celery. A questi si aggiungono queli definiti da altri pacchetti, per noi jobtastic che aggiunge PROGRESS con la percentuale di avanzamento
il broker è il sistema di messaggistica usato per accodare i task che celery esegue
il backend è il sistema con cui vengono cominucati/ispezionati gli stati del task
Note
Per visulalizzare correttamente i messaggi con URL prodotti nell’esempio dei task, occorre impostare il MESSAGE_STORAGE come spiegato in Link per messaggi
Per debuggare il codice mentre si utilizza un task eseguire i seguenti comandi:
from celery.contrib import rdb; rdb.set_trace()Verrà visualizazto un messaggio contenente l’url al quale collegarsi via telnet per effettuare il debug.