español python heroku rabbitmq celery sigterm

python - heroku español



Capturar a Heroku SIGTERM en trabajadores de apio para cerrar al trabajador con gracia (2)

He investigado un montón sobre esto, y me sorprende que no haya encontrado una buena respuesta a esto en ninguna parte.

Estoy ejecutando una aplicación grande en Heroku, y tengo ciertas tareas de apio que se ejecutan durante mucho tiempo en el procesamiento, y al final de la tarea, guardar un resultado. Cada vez que vuelvo a desplegar en Heroku, envía SIGTERM (y eventualmente, SIGKILL) y mata a mi trabajador de carrera. Estoy tratando de encontrar una forma para que la instancia de trabajo se cierre con gracia y se vuelva a poner en cola para procesarla más tarde, de modo que finalmente podamos guardar el resultado requerido en lugar de perder la tarea en cola.

No puedo encontrar una manera que funcione para que el trabajador escuche el SIGTERM correctamente. Lo más cercano que he conseguido, que funciona cuando se ejecuta python manage.py celeryd directamente, pero NO cuando se emula a Heroku usando el capataz, es lo siguiente:

@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!'')

Cuando comienzo esta tarea de apio que se ejecuta dentro de foreman y presiono Ctrl + C, sucede lo siguiente:

^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

Así que está claro que ninguna de las excepciones de apio, ni las excepciones de KeyboardInterrupt o SystemExit que he visto en otras publicaciones, capturan adecuadamente SIGTERM y cierran al trabajador.

¿Cuál es la forma correcta de hacer esto?


El apio no fue diseñado para hacer un cierre limpio. SIEMPRE. Lo digo en serio. los trabajadores del apio responden a SIGTERM, pero si una tarea está incompleta, los procesos de los trabajadores esperarán para finalizar la tarea y solo luego saldrán. En cuyo caso, puede enviarlo SIGKILL si los trabajadores no cierran en un tiempo razonable, pero habrá una pérdida de información en este caso, es decir, es posible que no sepa qué trabajos quedaron incompletos.


Puedes usar acks_late o task_acks_late .

Se reconocerán las tareas de la cola después de que se ejecuten las tareas y no solo antes. Así que la tarea reaparecerá si el trabajador se cierra con gracia.