celery celerybeat

El trabajo alrededor de celerybeat es un único punto de falla



(1)

Estoy buscando la solución recomendada para solucionar el problema de apio, ya que es un punto único de falla para la implementación de apio / conejo. No encontré nada que tuviera sentido hasta ahora, buscando en la web.

En mi caso, el programador programado una vez al día inicia una serie de trabajos que podrían ejecutarse durante medio día o más. Dado que solo puede haber una instancia de celerybeat, si algo le sucede a él o al servidor en el que se está ejecutando, los trabajos críticos no se ejecutarán.

Espero que ya exista una solución funcional para esto, ya que no puedo ser el único que necesita un programador confiable (agrupado o similar). No quiero recurrir a algún tipo de planificador respaldado por bases de datos, si no tengo que hacerlo.


Hay un tema abierto en el apio github repo sobre esto. Aunque no sé si están trabajando en ello.

Como solución alternativa, puede agregar un bloqueo para las tareas de modo que solo se ejecute una instancia de PeriodicTask específica a la vez.

Algo como:

if not cache.add(''My-unique-lock-name'', True, timeout=lock_timeout): return

Descubrir el tiempo de espera de bloqueo es bueno, complicado. Estamos usando 0.9 * task run_every segundos si diferentes celerybeats intentarán ejecutarlos en diferentes momentos. 0.9 solo para dejar algo de margen (p. Ej., Cuando el apio está un poco atrasado en el programa una vez, entonces está programado lo que haría que el bloqueo aún estuviera activo).

Luego puedes usar la instancia de celerybeat en todas las máquinas. Cada tarea se pondrá en cola para cada instancia de celerybeat, pero solo una de ellas finalizará la ejecución.

Las tareas seguirán respetando run_every de esta manera, en el peor de los casos: las tareas se ejecutarán a una velocidad de 0.9 * run_every.

Un problema con este caso: si las tareas se pusieron en cola pero no se procesaron en el tiempo programado (por ejemplo, porque los procesadores de colas no estaban disponibles), entonces el bloqueo puede colocarse en el momento incorrecto y posiblemente no se ejecute la siguiente tarea. Para solucionar esto, necesitaría algún tipo de mecanismo de detección si la tarea es más o menos puntual.

Aún así, esta no debería ser una situación común cuando se usa en producción.

Otra solución es subclasificar el programador de celerybeat y anular su método tick. Luego, para cada tick, agregue un bloqueo antes de procesar las tareas. Esto asegura que solo celerybeats con las mismas tareas periódicas no haga la misma cola varias veces. Solo un celerybeat por cada tick (uno que gana la condición de carrera) pondrá en cola las tareas. En un celerybeat baja, con la siguiente tick otra ganará la carrera.

Por supuesto, esto se puede utilizar en combinación con la primera solución.

Por supuesto, para que esto funcione, el backend del caché debe ser replicado y / o compartido para todos los servidores.

Es una vieja pregunta pero espero que ayude a cualquiera.