Uso de Celery para consultas en tiempo real y sincrónicas de la API con Gevent

Estoy trabajando en una aplicación web que recibirá una solicitud de un usuario y tendrá que acceder a una serie de API externas para componer la respuesta a esa solicitud. Esto se puede hacer directamente desde el hilo principal de la web usando algo como gevent para expandir la solicitud.

Alternativamente, estaba pensando, podría poner las solicitudes entrantes en una cola y usar trabajadores para distribuir la carga. La idea sería tratar de mantenerlo en tiempo real, mientras se dividen las solicitudes entre varios trabajadores. Cada uno de estos trabajadores estaría consultando solo una de las muchas API externas. La respuesta que reciban pasaría por una serie de transformaciones, se guardaría en una base de datos, se transformaría en un esquema común y se guardaría en una base de datos común para finalmente componerse en una gran respuesta que se devolvería a través de la solicitud web. Es muy probable que la solicitud web se bloquee todo este tiempo, con un usuario esperando, por lo que es importante mantener la cola y el retiro de la cola lo más rápido posible.

Las llamadas API externas se pueden convertir fácilmente en tareas individuales. Creo que la vinculación de una tarea de api a una transformación a una tarea de guardado de base de datos se podría hacer usando una cadena, etc., y el resultado final combinando todos los resultados devueltos al hilo web usando un acorde.

Algunas preguntas:

  • ¿Puede (y debería) hacerse esto usando apio?
  • Estoy usando django. ¿Debo intentar usar django-apio sobre apio natural?
  • Cada una de esas tareas puede generar otras tareas, como el registro de lo que acaba de suceder u otros tipos de ramificación. es posible?
  • ¿Podrían las tareas devolver los datos que obtienen, es decir, potencialmente Kb de datos a través del apio (los redis como subyacentes en este caso) o deberían escribir en la base de datos, y simplemente pasar los punteros a esos datos?
  • Cada tarea está mayormente vinculada a la E / S, e inicialmente solo iba a usar gevent del hilo web para desplegar las solicitudes y omitir todo el diseño de la cola, pero resulta que se reutilizaría para un componente diferente. Tratar de mantener todo el viaje de ida y vuelta en tiempo real en Qs probablemente requerirá que muchos trabajadores se aseguren de que la cola esté casi vacía. ¿O es eso? ¿Funcionaría con el grupo de trabajadores de gevent?
  • ¿Tengo que escribir tareas específicas de gevent o el uso de gevent pool tratará con la red IO de forma automática?
  • ¿Es posible asignar prioridad a ciertas tareas?
  • ¿Qué hay de mantenerlos en orden?
  • ¿Debo saltear el apio y solo usar kombu?
  • Parece que el apio está más orientado hacia “tareas” que pueden diferirse y no son sensibles al tiempo. ¿Estoy loco por tratar de mantener esto en tiempo real?
  • ¿Qué otras tecnologías debo mirar?

Actualización: Tratando de hash esto un poco más. Leí algo sobre Kombu y parece que puedo hacer lo que estoy pensando, aunque a un nivel mucho más bajo que el apio. Aquí hay un diagtwig de lo que tenía en mente. Es una versión simplificada, es decir, omitiendo los pasos de guardado de DB realizados por worker_2.

Lo que parece ser posible con las colas sin procesar a las que se puede acceder con Kombu es la capacidad de varios trabajadores para suscribirse a un mensaje de difusión. El editor no necesita conocer el tipo y el número si utiliza una cola. ¿Se puede lograr algo similar usando el apio? Parece que si desea hacer un acorde, necesita saber en el tiempo de ejecución qué tareas van a involucrarse en el acorde, mientras que en este escenario simplemente puede agregar oyentes a la transmisión, y simplemente asegurarse de que anuncien que están en el acorde. la ejecución para agregar respuestas a la cola final.

Actualización 2: veo que existe la posibilidad de transmitir ¿Puedes combinar esto con un acorde? En general, ¿puedes combinar el apio con el kombu crudo? Esto está empezando a sonar como una pregunta acerca de los batidos.

Intentaré responder la mayor cantidad de preguntas posible.

¿Puede (y debería) hacerse esto usando apio?

sí tu puedes

Estoy usando django. ¿Debo intentar usar django-apio sobre apio natural?

Django tiene un buen soporte para el apio y facilitaría mucho la vida durante el desarrollo.

Cada una de esas tareas puede generar otras tareas, como el registro de lo que acaba de suceder u otros tipos de ramificación. es posible?

Puede iniciar subtareas desde una tarea con ignore_result = true solo para efectos secundarios

¿Podrían las tareas devolver los datos que obtienen, es decir, potencialmente Kb de datos a través del apio (los redis como subyacentes en este caso) o deberían escribir en la base de datos, y simplemente pasar los punteros a esos datos?

Yo sugeriría poner los resultados en db y luego pasar la identificación haría que su agente y sus trabajadores estén contentos. Menos transferencia de datos / decapado etc.

Cada tarea está mayormente vinculada a la E / S, e inicialmente solo iba a usar gevent del hilo web para desplegar las solicitudes y omitir todo el diseño de la cola, pero resulta que se reutilizaría para un componente diferente. Tratar de mantener todo el viaje de ida y vuelta en tiempo real en Qs probablemente requerirá que muchos trabajadores se aseguren de que la cola esté casi vacía. ¿O es eso? ¿Funcionaría con el grupo de trabajadores de gevent?

Dado que el proceso está limitado, gevent definitivamente ayudará aquí. Sin embargo, la cantidad de concurrencia que debe ser para el trabajador de gevent pool’d es algo que también estoy buscando respuesta.

¿Tengo que escribir tareas específicas de gevent o el uso de gevent pool tratará con la red IO de forma automática?

Gevent hace el parche del mono automáticamente cuando lo usas en la piscina. Pero las bibliotecas que uses deberían jugar bien con gevent. De lo contrario, si analiza algunos datos con simplejson (que está escrito en c), entonces se bloquearán otros greenlets de gevent.

¿Es posible asignar prioridad a ciertas tareas?

No puede asignar prioridades específicas a ciertas tareas, pero enrutarlas a una cola diferente y luego hacer que esas colas sean escuchadas por un número variable de trabajadores. Cuanto más trabajen los trabajadores para una cola en particular, mayor será la prioridad de las tareas en esa cola.

¿Qué hay de mantenerlos en orden?

La cadena es una forma de mantener el orden. Acorde es una buena manera de resumir. El apio lo cuida, así que no tienes que preocuparte por eso. Incluso cuando se usa gevent pool, al final sería posible razonar sobre el orden de ejecución de las tareas.

¿Debo saltear el apio y solo usar kombu?

Usted puede, si su caso de uso no cambiará a algo más complejo con el tiempo y también si está dispuesto a administrar sus procesos a través de celeryd + supervisord por usted mismo. Además, si no te importa el monitoreo de tareas que viene con herramientas como celerymon, flower, etc.

Parece que el apio está más orientado hacia “tareas” que pueden diferirse y no son sensibles al tiempo.

El apio soporta tareas progtwigdas también. Si eso es lo que querías decir con esa statement.

¿Estoy loco por tratar de mantener esto en tiempo real?

No lo creo. Mientras sus consumidores sean lo suficientemente rápidos, será tan bueno como el tiempo real.

¿Qué otras tecnologías debo mirar?

Perteneciente al apio, debe elegir sabiamente la tienda de resultados. Mi sugerencia sería utilizar cassandra. Es bueno para datos en tiempo real (tanto de escritura como de consulta). También puedes usar redis o mongodb. Vienen con su propio conjunto de problemas como resultado de la tienda. Pero entonces un poco de ajuste en la configuración puede recorrer un largo camino.

Si te refieres a algo completamente diferente al apio, entonces puedes buscar en asyncio (python3.5) y zeromq para lograr lo mismo. Aunque no puedo comentar más sobre eso.