Comprender la obtención previa de tareas de apio

79

Me acabo de enterar de la opción de configuración CELERYD_PREFETCH_MULTIPLIER( documentos ). El valor predeterminado es 4, pero (creo) quiero que la captación previa esté desactivada o lo más baja posible. Lo configuré en 1 ahora, que está lo suficientemente cerca de lo que estoy buscando, pero todavía hay algunas cosas que no entiendo:

  1. ¿Por qué esta búsqueda previa es una buena idea? Realmente no veo una razón para ello, a menos que haya mucha latencia entre la cola de mensajes y los trabajadores (en mi caso, actualmente se están ejecutando en el mismo host y, en el peor de los casos, podrían eventualmente ejecutarse en diferentes hosts en los mismos datos centrar). La documentación solo menciona las desventajas, pero no explica cuáles son las ventajas.

  2. Mucha gente parece establecer esto en 0, esperando poder desactivar la captación previa de esa manera (una suposición razonable en mi opinión). Sin embargo, 0 significa captura previa ilimitada. ¿Por qué alguien querría una búsqueda previa ilimitada? ¿No elimina eso por completo la concurrencia / asincronicidad para la que introdujo una cola de tareas en primer lugar?

  3. ¿Por qué no se puede desactivar la captación previa? Puede que no sea una buena idea que el rendimiento lo desactive en la mayoría de los casos, pero ¿hay alguna razón técnica para que esto no sea posible? ¿O simplemente no está implementado?

  4. A veces, esta opción está conectada a CELERY_ACKS_LATE. Por ejemplo. Roger Hu escribe «[…] a menudo lo que [los usuarios] realmente quieren es que un trabajador solo reserve tantas tareas como procesos secundarios haya. Pero esto no es posible sin habilitar los reconocimientos tardíos […] »No entiendo cómo están conectadas estas dos opciones y por qué una no es posible sin la otra. Aquí se puede encontrar otra mención de la conexión . ¿Alguien puede explicar por qué las dos opciones están conectadas?

Henrik Heimbuerger
fuente

Respuestas:

32
  1. La captación previa puede mejorar el rendimiento. Los trabajadores no necesitan esperar a que se procese el siguiente mensaje de un corredor. Comunicarse con un corredor una vez y procesar una gran cantidad de mensajes proporciona una ganancia de rendimiento. Recibir un mensaje de un corredor (incluso de uno local) es caro en comparación con el acceso a la memoria local. Los trabajadores también pueden reconocer mensajes en lotes

  2. La captación previa establecida en cero significa "sin límite específico" en lugar de ilimitado

  3. Se documenta que establecer la captación previa en 1 equivale a desactivarlo, pero no siempre es así (consulte https://stackoverflow.com/a/33357180/71522 )

  4. La captación previa permite confirmar mensajes en lotes. CELERY_ACKS_LATE = True evita reconocer mensajes cuando llegan a un trabajador

mher
fuente
Gracias. 2) Está bien, pero ¿por qué alguien querría 'ningún límite específico'? 3) Estoy bastante seguro de que todavía veo los mensajes "Obtuve la tarea del corredor" antes de que finalice la tarea actual.
Henrik Heimbuerger
1
AFAIK, establecer la captación previa en 1 no es equivalente a apagarlo. Es el valor más bajo posible (sin piratear el código fuente) para la captación previa, que, a su vez, es la cantidad de CPU / núcleos en la máquina actual.
Ron Klein
1
@RonKlein No es la cantidad de CPU / núcleos, es la cantidad de trabajadores de Apio que ha definido (que en algunos casos puede ser el mismo, pero generalmente no). Además, si cada trabajador está precargando una sola tarea, luego ejecutándola, luego precargando otra, esto es equivalente a desactivar la precarga, por lo que en mi humilde opinión su declaración es incorrecta. (El sistema siempre debe buscar previamente tantas tareas como trabajadores haya si quiere mantener a todos los trabajadores alimentados con tareas.)
nitwit
3
Creo que CELERYD_PREFETCH_MULTIPLIER establecido en 1 básicamente significa 'buscar'. La búsqueda previa está implícita cuando el valor se establece en> 1. Entonces, en efecto, las tareas más allá de 1 se están "precargadas".
tigeronk2
3
Me he encontrado algunos experimentos, y (al menos con los Redis broker) configuración CELERYD_PREFETCH_MULTIPLIER = 1hace no la obtención previa de bloqueo. Simplemente, como su nombre indica, solo precarga una tarea a la vez.
David Wolever
28

Pregunta anterior, pero aún agrego mi respuesta en caso de que ayude a alguien. Mi comprensión de algunas pruebas iniciales fue la misma que la de la respuesta de David Wolever. Acabo de probar esto más en apio 3.1.19 y -Ofairfunciona. Solo que no está destinado a deshabilitar la captación previa en el nivel del nodo de trabajo. Eso seguirá sucediendo. El uso -Ofairtiene un efecto diferente que se encuentra en el nivel del trabajador de la piscina. En resumen, para deshabilitar la captación previa por completo, haga lo siguiente:

  1. Conjunto CELERYD_PREFETCH_MULTIPLIER = 1
  2. Establecer CELERY_ACKS_LATE = Truea nivel global o nivel de tarea
  3. Úselo -Ofairal iniciar los trabajadores
  4. Si establece la simultaneidad en 1, el paso 3 no es necesario. Si desea una mayor simultaneidad, el paso 3 es esencial para evitar que las tareas se respalden en un nodo que podría ejecutar tareas de larga duración.

Añadiendo algunos detalles más:

Descubrí que el nodo trabajador siempre se buscará previamente de forma predeterminada. Solo puede controlar la cantidad de tareas que solicita previamente mediante CELERYD_PREFETCH_MULTIPLIER. Si se establece en 1, solo precargará tantas tareas como el número de trabajadores del grupo (simultaneidad) en el nodo. Entonces, si tenía concurrencia = n, el número máximo de tareas precargadas por el nodo será n.

Sin la -Ofairopción, lo que me sucedió fue que si uno de los procesos de trabajo del grupo estaba ejecutando una tarea de ejecución prolongada, los otros trabajadores del nodo también dejarían de procesar las tareas que ya había obtenido previamente. Al usar -Ofair, eso cambió. Aunque uno de los trabajadores en el nodo estaba ejecutando tareas de larga ejecución, otros no dejarían de procesar y continuarían procesando las tareas precargadas por el nodo. Veo dos niveles de obtención previa. Uno en el nivel del nodo trabajador. El otro a nivel de trabajador individual. Usar -Ofairpara mí parecía deshabilitarlo a nivel de trabajador.

¿Cómo se ACKS_LATErelaciona? ACKS_LATE = Truesignifica que la tarea se reconocerá solo cuando la tarea se realice correctamente. De lo contrario, supongo que pasaría cuando lo reciba un trabajador. En el caso de la captación previa, el trabajador primero recibe la tarea (confirmada a partir de los registros) pero se ejecutará más tarde . Me acabo de dar cuenta de que los mensajes precargados aparecen en "mensajes no reconocidos" en rabbitmq. Así que no estoy seguro de si Truees absolutamente necesario configurarlo . De todos modos, teníamos nuestras tareas configuradas de esa manera (ack tardío) por otras razones.

ksrini
fuente
¡Gracias por seguir contribuyendo a esta pregunta! ¿Podrías agregar un poco más de detalle? Por ejemplo, lo que estás escribiendo -Ofairtiene un "efecto diferente", pero no en qué se diferencia el efecto. Además, estás mencionando CELERY_ACKS_LATE, como otros lo han hecho antes, pero hasta ahora nadie ha logrado explicarme qué tiene que ver ese atributo con la desactivación de la captación previa.
Henrik Heimbuerger
Tuve este mismo problema, ejecutándose con un backend de redis. Tenía 4 tareas simultáneas en ejecución y cuando una comenzaba a colgar, las otras esperaban a que terminara (no lo haría): matar a ese trabajador permitiría que otros se reanudaran. Ya lo había hecho prefetch=1, celery_acks=Truey cuando lo agregué -Ofairsolucionó el problema en el que estaban esperando al trabajador colgado. Desafortunadamente, el problema del trabajador colgado todavía no se solucionó para mí y, por lo tanto, todos los trabajadores eventualmente se cuelgan, pero al menos ya no lo hacen exactamente al mismo tiempo.
JiminyCricket
18

Solo una advertencia: a partir de mis pruebas con el corredor de redis + Celery 3.1.15, todos los consejos que he leído relacionados con la CELERYD_PREFETCH_MULTIPLIER = 1desactivación de la captación previa son demostrablemente falsos.

Para demostrar esto:

  1. Conjunto CELERYD_PREFETCH_MULTIPLIER = 1
  2. Ponga en cola 5 tareas que tomarán unos segundos cada una (por ejemplo, time.sleep(5))
  3. Comience a ver la longitud de la cola de tareas en Redis: watch redis-cli -c llen default

  4. comienzo celery worker -c 1

  5. Tenga en cuenta que la longitud de la cola en Redis caerá inmediatamente de 5a3

CELERYD_PREFETCH_MULTIPLIER = 1 no evita la captación previa , simplemente limita la captación previa a 1 tarea por cola.

-Ofair, a pesar de lo que dice la documentación , tampoco impide la captación previa .

Aparte de modificar el código fuente, no he encontrado ningún método para deshabilitar por completo la captación previa.

David Wolever
fuente
1
Como han mencionado otras respuestas, si también lo configura CELERY_ACKS_LATE = 1, deshabilitará efectivamente la captación previa.
jodag
11

No puedo comentar sobre las respuestas de David Wolever, ya que mi stackcred no es lo suficientemente alto. Entonces, he enmarcado mi comentario como una respuesta ya que me gustaría compartir mi experiencia con Celery 3.1.18 y un corredor de Mongodb. Me las arreglé para dejar de buscar previamente con lo siguiente:

  1. agregar CELERYD_PREFETCH_MULTIPLIER = 1a la configuración de apio
  2. agregar CELERY_ACKS_LATE = Truea la configuración de apio
  3. Inicie el trabajador de apio con opciones: --concurrency=1 -Ofair

Dejando CELERY_ACKS_LATE en el valor predeterminado, el trabajador aún realiza búsquedas anticipadas. Al igual que el OP, no entiendo completamente el vínculo entre la captación previa y los acks tardíos. Entiendo lo que dice David "CELERY_ACKS_LATE = True impide reconocer mensajes cuando llegan a un trabajador", pero no entiendo por qué los acks tardíos serían incompatibles con la captación previa. En teoría, una captación previa aún permitiría ack tardío, ¿incluso si no se codifica como tal en el apio?

Paul-Armand Verhaegen
fuente
2

Experimenté algo un poco diferente con SQS como corredor.

La configuración fue:

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

Después de que la tarea fallara (se generó una excepción), el trabajador dejó de estar disponible porque el mensaje no fue recibido, tanto en la cola local como en la remota.

La solución que hizo que los trabajadores siguieran consumiendo trabajo fue establecer

CELERYD_PREFETCH_MULTIPLIER = 0

Solo puedo especular que acks_late no se tuvo en cuenta al escribir el transporte SQS

gCoh
fuente
Creé
gCoh