Estoy escribiendo una aplicación en Flask, que funciona muy bien, excepto que WSGI
es sincrónica y de bloqueo. Tengo una tarea en particular que llama a una API de terceros y esa tarea puede tardar varios minutos en completarse. Me gustaría hacer esa llamada (en realidad es una serie de llamadas) y dejar que se ejecute. mientras que el control se devuelve a Flask.
Mi vista se parece a:
@app.route('/render/<id>', methods=['POST'])
def render_script(id=None):
...
data = json.loads(request.data)
text_list = data.get('text_list')
final_file = audio_class.render_audio(data=text_list)
# do stuff
return Response(
mimetype='application/json',
status=200
)
Ahora, lo que quiero hacer es tener la línea
final_file = audio_class.render_audio()
ejecutar y proporcionar una devolución de llamada para que se ejecute cuando el método regrese, mientras que Flask puede continuar procesando solicitudes. Esta es la única tarea que necesito que Flask se ejecute de forma asincrónica, y me gustaría recibir algunos consejos sobre la mejor manera de implementar esto.
He mirado a Twisted y Klein, pero no estoy seguro de que sean exagerados, ya que tal vez Threading sería suficiente. ¿O tal vez el apio es una buena opción para esto?
fuente
Respuestas:
Me gustaría utilizar apio para manejar la tarea asíncrona para usted. Deberá instalar un agente para que sirva como cola de tareas (se recomiendan RabbitMQ y Redis).
app.py
:Ejecute su aplicación Flask e inicie otro proceso para ejecutar su trabajador de apio.
También me referiría a Miguel Gringberg escritura hasta una más en la guía de profundidad a la utilización de apio con el frasco.
fuente
El enhebrado es otra posible solución. Aunque la solución basada en apio es mejor para aplicaciones a escala, si no espera demasiado tráfico en el punto final en cuestión, el subproceso es una alternativa viable.
Esta solución se basa en la presentación PyCon 2016 Flask at Scale de Miguel Grinberg , específicamente en la diapositiva 41 de su plataforma de diapositivas. Su código también está disponible en github para aquellos interesados en la fuente original.
Desde la perspectiva del usuario, el código funciona de la siguiente manera:
Para convertir una llamada a la API en una tarea en segundo plano, simplemente agregue el decorador @async_api.
Aquí hay un ejemplo completo:
fuente
También puede intentar usar
multiprocessing.Process
condaemon=True
; elprocess.start()
método no se bloquea y puede devolver una respuesta / estado inmediatamente a la persona que llama mientras su costosa función se ejecuta en segundo plano.Experimenté un problema similar mientras trabajaba con el marco de Falcon y el
daemon
proceso me ayudó.Debería hacer lo siguiente:
Debería obtener una respuesta de inmediato y, después de 10 segundos, debería ver un mensaje impreso en la consola.
NOTA: Tenga en cuenta que los
daemonic
procesos no pueden generar procesos secundarios.fuente
/render/<id>
pasa si endpoint espera algo como resultado demy_func()
?my_func
enviar respuesta / latidos a algún otro punto final, por ejemplo. O puede establecer y compartir una cola de mensajes a través de la cual puede comunicarse conmy_func