2012-03-10 14 views
24

Utilizziamo Celery con la nostra app web Django per gestire le attività offline; alcune di queste attività possono essere eseguite fino a 120 secondi.Come riavviare Celery senza ritardi delle attività

Ogni volta che apportiamo modifiche al codice, è necessario riavviare Celery per farlo ricaricare il nuovo codice Python. La nostra soluzione attuale è quella di inviare un SIGTERM al processo principale di Celery (kill -s 15 `cat /var/run/celeryd.pid`), quindi attendere che muoia e riavviarlo (python manage.py celeryd --pidfile=/var/run/celeryd.pid [...]).

A causa delle attività a esecuzione prolungata, questo di solito significa che lo spegnimento richiederà un minuto o due, durante il quale non vengono elaborate nuove attività, causando un ritardo evidente agli utenti attualmente sul sito. Sto cercando un modo per dire a Celery di spegnersi, ma poi lanciamo immediatamente una nuova istanza di Celery per iniziare a eseguire nuovi compiti.

Le cose non che ha fatto lavoro:

  • Invio SIGHUP al processo principale: questo ha causato sedano per tentare di "restart", effettuando un arresto caldo e poi rilanciare se stessa. Non solo ci vuole molto tempo, non funziona nemmeno, perché apparentemente il nuovo processo si avvia prima che il vecchio muore, quindi il nuovo si lamenta ERROR: Pidfile (/var/run/celeryd.pid) already exists. Seems we're already running? (PID: 13214) e muore immediatamente. (Questo sembra un bug in Celery stesso, ho let them know a riguardo.)
  • Invio di SIGTERM al processo principale e quindi avvio immediato di una nuova istanza: stesso problema con il file Pid.
  • Disabilitare completamente il Pidfile: senza di esso, non abbiamo modo di dire quale dei 30 processi di Celery sia il processo principale che deve essere inviato a SIGTERM quando vogliamo che esegua un arresto caldo. Non abbiamo neanche un modo affidabile per verificare se il processo principale è ancora vivo.
+0

Forse la mia risposta di http://stackoverflow.com/questions/9764913/how-do-i-restart-celery-workers-gracefully/16717128#16717128 ti aiuta. – guettli

risposta

0

Puoi lanciarlo con un nome di file pid personalizzato. Forse timestamped, e chiave fuori di quello per sapere quale PID uccidere?

CELERYD_PID_FILE="/var/run/celery/%n_{timestamp}.pid"

^io non so la sintassi timestamp ma forse si fa o si può trovare?

quindi utilizzare l'ora corrente del sistema per eliminare i vecchi pid e avviarne uno nuovo?

+0

Sospetto che avrai bisogno di una combinazione di una delle tecniche nella domanda con questo. A seconda del tuo broker, dovresti essere in grado di avviare un nuovo sedano con un file pid basato su timestamp (usando '--pidfile ='), quindi inviare 'SIGTERM' a tutti gli altri processi di sedimentazione in esecuzione per farli scaldare shutdown (anche se nota che dovrebbe essercene solo uno, a meno che non provi questo mentre un vecchio sedano sta ancora attraversando un arresto caldo). –

4

celeryd ha l'opzione --autoreload. Se abilitato, il gestore di sedici (processo principale) rileverà le modifiche nei moduli di celery e riavvierà tutti i processi di lavoro. Al contrario del segnale SIGHUP, il riavvio automatico riavvia ciascun processo in modo indipendente al termine dell'attività di esecuzione corrente. Significa che mentre un processo di lavoro è in fase di riavvio, i processi rimanenti possono eseguire attività.

http://celery.readthedocs.org/en/latest/userguide/workers.html#autoreloading

+14

Sebbene '--autoreload' sia contrassegnato come non consigliato per la distribuzione dal vivo. –

+1

In produzione può essere utilizzato con un reloader personalizzato come questo http://www.indelible.org/ink/python-reloading/ – mher

3

Recentemente ho fissato il bug con SIGHUP: https://github.com/celery/celery/pull/662

+0

Grazie! Tuttavia, la tua correzione non cambia il fatto che SIGHUP aspetta che tutte le attività finiscano prima di terminare e riavviare, causando di nuovo il ritardo che sto tentando di evitare. Idee su come trarre vantaggio dalla tua correzione e tuttavia farlo rilanciare senza aspettare sarebbe grandioso ... – nitwit

+0

Ecco come ho risolto il problema. Inserisco tutte le attività di lunga durata (conversione video, consegna di email) in una coda separata, che viene elaborata da un lavoratore separato. Così, quando invio SIGHUP a tutti i lavoratori, so che le operazioni di elaborazione dei lavori dalla coda predefinita non si bloccano a lungo, perché ci sono solo piccole attività. La conversione video non blocca le piccole attività. Solo la coda di conversione video è bloccata per un po '. Ma questo è accettabile nel mio caso. –

+0

Quindi, dopo alcuni test, ho scoperto che la tua correzione risolve anche il problema SIGTERM. Così finalmente sono riuscito a risolvere questo problema una volta per sempre unendo la tua correzione e riavvio di Celery usando: 'kill -s SIGTERM' 'cat/var/run/celeryd.pid'' && python manage.py celeryd --pidfile =/var/run/celeryd.pid [...] ' Se riesci a metterlo nella tua risposta, lo accetto! – nitwit

2
rm *.pyc 

In questo modo l'attività aggiornate per essere ricaricate. Ho scoperto questo trucco di recente, spero solo che non ci siano effetti collaterali sgradevoli.

0

Bene, si utilizza SIGHUP (1) per l'arresto a caldo del sedano. Non sono sicuro che causi effettivamente uno spegnimento caldo. Ma SIGINT (2) causerebbe un arresto caldo. Prova SIGINT al posto di SIGHUP e poi avvia il sedano manualmente nel tuo script (credo).

1

Un po 'tardi, ma che può fissato dal eliminando il file chiamato celerybeat.pid.

Ha funzionato per me.