Python “Servidor de tareas”

Mi pregunta es: ¿qué marco de Python debo usar para construir mi servidor?

Notas:

  • Este servidor habla HTTP con sus clientes: GET y POST (a través de pyAMF)
  • Los clientes “envían” “tareas” para su procesamiento y, luego, más tarde, recuperan el “task_result” asociado
  • El envío y la recuperación pueden estar separados por días: diferentes conexiones HTTP
  • La “tarea” es un grupo de XML que describe un problema que debe resolverse, y un “task_result” es un grupo de XML que describe una respuesta.
  • Cuando un servidor obtiene una “tarea”, la pone en cola para su procesamiento
  • El servidor gestiona esta cola y, cuando las tareas llegan a la cima, organiza su procesamiento.
  • el procesamiento se realiza mediante un progtwig externo de ejecución prolongada (¿15 min?) (a través de un subproceso) que alimenta la tarea XML y que produce un grupo “task_result” de XML que el servidor recoge y almacena (para su posterior recuperación del Cliente).
  • sirve un par de páginas HTML básicas que muestran la cola y el estado de procesamiento (solo con fines de administración)

He experimentado con twisted.web, utilizando SQLite como base de datos y subprocesos para manejar los procesos de larga ejecución.

Pero no puedo evitar sentir que me falta una solución más simple. Soy yo Si se enfrentara a esto, ¿qué combinación de tecnología usaría?

Recomiendo usar una cola de mensajes existente. Hay muchos para elegir (ver más abajo), y varían en complejidad y solidez.

Además, evite los subprocesos: deje que sus tareas de procesamiento se ejecuten en un proceso diferente (¿por qué tienen que ejecutarse en el servidor web?)

Al utilizar una cola de mensajes existente, solo debe preocuparse por generar mensajes (en su servidor web) y consumirlos (en sus tareas de larga ejecución). A medida que su sistema crezca, podrá ampliarse simplemente agregando servidores web y consumidores, y preocupándose menos por su infraestructura de colas.

Algunas implementaciones populares de python de colas de mensajes:

Sugeriría lo siguiente. (Ya que es lo que estamos haciendo).

Un servidor WSGI simple ( wsgiref o werkzeug ). Las solicitudes HTTP que entran naturalmente formarán una cola. No se necesitan más colas. Recibes una solicitud, engendras el subproceso como un niño y esperas a que termine. Una simple lista de niños es todo lo que necesitas.

Utilicé una modificación del bucle principal de “servir para siempre” en wsgiref para encuestar periódicamente a todos los niños para ver cómo están.

Una simple base de datos SQLite puede rastrear el estado de la solicitud. Incluso esto puede ser una exageración porque sus entradas y resultados XML solo pueden estar en el sistema de archivos.

Eso es. La cola y los hilos realmente no entran en ella. Un solo proceso externo de larga ejecución es demasiado complejo para coordinar. Es más sencillo si cada solicitud es un proceso secundario independiente y autónomo.

Si recibe una gran cantidad de solicitudes, es posible que desee un simple gobernador para evitar la creación de miles de niños. El gobernador podría ser una cola simple, construida usando una lista con append () y pop (). Todas las solicitudes entran, pero solo se eliminan las solicitudes que se ajustan dentro de algún límite de “número máximo de hijos”.

Mi reacción es sugerir Twisted, pero ya has mirado esto. Aún así, me quedo con mi respuesta. Sin conocer sus puntos de dolor personales, al menos puedo compartir algunas cosas que me ayudaron a reducir casi toda la locura diferida que surge cuando tiene varias acciones de locking dependientes que debe realizar para un cliente.

Las devoluciones de llamada en línea (ligeramente documentadas aquí: http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.html ) proporcionan un medio para hacer que las largas cadenas de aplazados sean mucho más legibles (hasta el punto de parecer código de línea recta). Hay un excelente ejemplo de la reducción de la complejidad que esto ofrece aquí: http://blog.mekk.waw.pl/archives/14-Twisted-inlineCallbacks-and-deferredGenerator.html

No siempre tiene que hacer que su procesamiento masivo se integre bien con Twisted. A veces es más fácil dividir una gran parte de su progtwig en una herramienta de línea de comandos independiente, fácilmente comprobable / modificable / implementable y hacer que Twisted invoque esta herramienta en otro proceso. ProcessProtocol de Twisted proporciona una forma bastante flexible de iniciar e interactuar con progtwigs de ayuda externos. Además, si de repente decides que quieres cloudificar tu aplicación, no es tan importante tratar de usar un ProcessProtocol para simplemente ejecutar tu procesamiento masivo en un servidor remoto (quizás instancias EC2 aleatorias) a través de ssh , asumiendo que tienes las claves configuración ya

Puedes echar un vistazo al apio.

Parece que cualquier framework web de Python se adaptará a tus necesidades. Trabajo con un sistema similar a diario y puedo decirle que su solución con subprocesos y SQLite para el almacenamiento de colas es tan simple como lo va a obtener.

Suponiendo que el orden no importa en su cola, entonces los hilos deberían ser aceptables. Es importante asegurarse de no crear condiciones de carrera con sus colas o, por ejemplo, tener dos del mismo tipo de trabajo ejecutándose simultáneamente. Si este es el caso, sugeriría una aplicación de un solo hilo para hacer los elementos en la cola uno por uno.