Ho fatto un sacco di ricerche su questo, e sono sorpreso di non aver trovato una buona risposta a questo ancora da nessuna parte.Cattura Heroku SIGTERM in lavoratori di Celery per spegnere il lavoratore con grazia
Sto eseguendo una grande applicazione su Heroku e ho alcune attività di sedici che vengono eseguite per un'elaborazione molto lunga, e alla fine dell'attività salvare un risultato. Ogni volta che effettuo il reimpiego su Heroku, invia SIGTERM (e alla fine SIGKILL) e uccide il mio lavoratore in esecuzione. Sto cercando di trovare un modo per l'istanza di lavoro di chiudersi in modo corretto e ri-accodare se stesso per l'elaborazione successiva in modo che alla fine possiamo salvare il risultato richiesto invece di perdere l'attività in coda.
Non riesco a trovare un modo che funzioni per consentire all'operatore di ascoltare SIGTERM correttamente. Il più vicino che ho ottenuto, che funziona quando si esegue python manage.py celeryd
direttamente, ma NON per l'emulazione di Heroku utilizza caposquadra, è la seguente:
@app.task(bind=True, max_retries=1)
def slow(self, x):
try:
for x in range(100):
print 'x: ' + unicode(x)
time.sleep(10)
except exceptions.MaxRetriesExceededError:
logger.error('whoa')
except (exceptions.WorkerShutdown, exceptions.WorkerTerminate) as exc:
logger.error(u'retrying, ' + unicode(exc))
raise self.retry(exc=exc, countdown=10)
except (KeyboardInterrupt, SystemExit) as exc:
print 'retrying'
raise self.retry(exc=exc, countdown=10)
else:
return x
finally:
logger.info('task ended!')
Quando inizio a questo compito sedano in esecuzione all'interno di caposquadra e premere CTRL + C, il succede questo:
^CSIGINT received
22:20:59 system | sending SIGTERM to all processes
22:20:59 web.1 | exited with code 0
22:21:04 system | sending SIGKILL to all processes
Killed: 9
Quindi è chiaro che nessuna delle eccezioni sedano, né i KeyboardInterrupt
o SystemExit
eccezioni che ho visto in altri post, prendere correttamente SIGTERM e spegnere il lavoratore.
Qual è il modo giusto per farlo?
http://celery.readthedocs.org/en/latest/userguide/workers.html?highlight=sigkill#process-signals sembra indicare che l'operatore principale intercetterà sempre SIGTERM. –
Giusto - quindi c'è un modo per far propagare il lavoratore principale ai bambini? – jdotjdot
Questo è un problema che non ho mai trovato un'ottima soluzione. Tendo a gestirlo in logica applicativa assicurandomi che i miei compiti siano idempotenti e il tracciamento delle attività avviate e completate in modo tale da consentire il riavvio automatico di una determinata attività all'avvio dell'applicazione. –