Tenemos un servicio web que sirve segmentos pequeños y arbitrarios de un inventario fijo de archivos MP3 más grandes. Los archivos MP3 se generan sobre la marcha con una aplicación de Python. El modelo es, realizar una solicitud GET a una URL especificando qué segmentos desea, obtener una transmisión audio/mpeg
en respuesta. Este es un proceso costoso.¿Existe alguna forma mejor de servir los resultados de un costoso proceso de bloqueo de python a través de HTTP?
Estamos utilizando Nginx como el controlador de solicitudes de la interfaz de usuario. Nginx se ocupa de las respuestas de caché para solicitudes comunes.
Inicialmente tratamos de usar Tornado en el back-end para manejar las solicitudes de Nginx. Como era de esperar, la operación de bloqueo de MP3 impidió que Tornado hiciera lo suyo (E/S asíncrona). Entonces, fuimos multiproceso, lo que resolvió el problema de bloqueo y funcionó bastante bien. Sin embargo, introdujo una sutil condición de carrera (bajo la carga del mundo real) que aún no hemos podido diagnosticar ni reproducir. La condición de carrera corrompe nuestra salida de MP3.
Así que decidimos configurar nuestra aplicación como un gestor de WSGI simple detrás de Apache/mod_wsgi (todavía con Nginx desde el principio). Esto elimina el problema de bloqueo y la condición de carrera, pero crea una carga en cascada (es decir, Apache crea demasiados procesos) en el servidor en condiciones del mundo real. Estamos trabajando para ajustar Apache/mod_wsgi en este momento, pero aún en una fase de prueba y error. (Actualización: hemos cambiado a Tornado. Consulte a continuación.)
Finalmente, la pregunta: ¿nos falta algo? ¿Hay una mejor manera de servir recursos costosos de CPU a través de HTTP?
Actualización: Gracias al artículo informado de Graham, estoy bastante seguro de que se trata de un problema de ajuste de Apache. Mientras tanto, hemos vuelto a usar Tornado y estamos tratando de resolver el problema de corrupción de datos.
Para aquellos que fueron tan rápidos para lanzar más hierro al problema, Tornado y un poco de multi-threading (a pesar del problema de integridad de datos introducido por el enhebrado) maneja la carga aceptablemente en una pequeña instancia de Amazon EC2 .
Excelente artículo. Gracias. Esto podría terminar haciendo el truco. –
De hecho, voy a aceptar este enlace como la mejor respuesta, ya que el problema parece ser un problema de ajuste de Apache. –