2012-09-25 14 views
40

Me gustaría enviar una solicitud REST local en un frasco de aplicación, así:Frasco tubería rota con las peticiones

from flask import Flask, url_for, request 
import requests 

app = Flask(__name__) 

@app.route("/<name>/hi", methods=["POST"]) 
def hi_person(name): 
    form = {"name": name} 
    return requests.post(url_for("hi", _external=True), data=form) 

@app.route("/hi", methods=["POST"]) 
def hi(): 
    return 'Hi, %s!' % request.form["name"] 

Envío curl -X POST http://localhost:5000/john/hi hace que todo el frasco de aplicación se congele. Cuando envío una señal de muerte, aparece un error de tubería roto. ¿Hay alguna manera de evitar que el matraz se congele aquí?

Respuesta

89

Ejecute su aplicación de matraz bajo un servidor WSGI adecuado capaz de manejar solicitudes concurrentes (quizás gunicorn o uWSGI) y funcionará. Durante el desarrollo, permitirá a las discusiones en el servidor suministrado por matraz con:

app.run(threaded=True) 

pero tenga en cuenta que el servidor frasco no está recomendado para su uso en producción.

Lo que pasa es que al utilizar las solicitudes está haciendo una segunda solicitud a su aplicación de matraz, pero como todavía está ocupado procesando la primera, no responderá a esta segunda solicitud hasta que se complete con esa primera solicitud .

Dicho sea de paso, en Python 3, la implementación de socketserver maneja la desconexión de forma más elegante y continúa funcionando en lugar de bloquearse.

+0

1, sin duda))><(( –

+2

que ejecutar la aplicación wsgi roscado pero me da la Tubería rota de todos modos: app.run (debug = true, roscado = True, host = '0.0. 0.0 ', puerto = 8080) – loretoparisi

+1

@loretoparisi: Sin detalles que es imposible de diagnosticar. Ejecutar el código en la pregunta con su línea 'app.run()' y el comando 'curl' ajustado funciona bien. Tal vez debería publicar un nuevo pregunta? –

16

Hay varias cosas en juego aquí, y trataré de resolverlas de una en una.

En primer lugar, probablemente esté utilizando el servidor de desarrollo de juguetes. Este servidor tiene muchas limitaciones; principalmente entre estas limitaciones es que solo puede manejar una solicitud a la vez. Cuando crea una segunda solicitud durante su primera solicitud, está bloqueando su aplicación: la función requests.post() está esperando que responda Flask, ¡pero el propio Flask está esperando que devuelva post()! La solución a este problema en particular es ejecutar su aplicación WSGI en un entorno multiproceso o multiproceso. Prefiero http://twistedmatrix.com/trac/wiki/TwistedWeb para esto, pero hay varias otras opciones.

Con eso fuera del camino ... Este es un antipatrón. Es casi seguro que no desea invocar todos los gastos generales de una solicitud HTTP solo para compartir alguna funcionalidad entre dos vistas. Lo correcto es refactorizar para tener una función separada que haga ese trabajo compartido. Realmente no puedo refactorizar tu ejemplo particular, porque lo que tienes es muy simple y realmente ni siquiera merece dos puntos de vista. ¿Qué querías construir, exactamente?

Editar: Un comentario pregunta si el modo multiproceso en el servidor stdlib de juguete sería suficiente para evitar que se produzca el interbloqueo. Voy a decir "tal vez". Sí, si no hay ninguna dependencia que impida que ambos subprocesos progresen y ambos subprocesos progresan lo suficiente para finalizar sus tareas de red, las solicitudes se completarán correctamente. Sin embargo, determinar si dos hilos se estancarán entre sí es indecidible (prueba omitida como obtusa) y no estoy dispuesto a decir con certeza si el servidor stdlib puede hacerlo bien.

+0

+1 hacer una solicitud dentro de un controlador de solicitud es malo en la mayoría de los casos, una solicitud http a ti mismo ... ick –

+0

Me encontré con el problema porque estaba fusionando dos servicios web que anteriormente se ejecutaba como procesos separados. La única interacción entre los dos servicios web fue ese POST. Los combiné en el mismo proceso usando blueprints y boom, se congeló. Entonces, un poco más de refactorización está en orden. – jfocht

+0

@Corbin también lo hace la opción roscado = Verdadero no es suficiente como TwistedWeb con respecto al multiprocesamiento y la ejecución de múltiples hilos en cada solicitud? – loretoparisi

3

El error que provocó el bloqueo fue fixed in Version 0.12, publicado el 21 de diciembre de 2016. ¡Sí! Esta es una solución importante que muchos han estado esperando.

De la lista de cambios Frasco:

  • revertir un cambio de comportamiento que hizo que la caída del servidor dev lugar de devolver un error interno del servidor (solicitud de extracción # 2006).
+0

¡Sí! Gracias por el consejo. La actualización al matraz 0.12 solucionó el problema. Ahora estos errores simplemente se registran sin bloquear mi servidor. –

Cuestiones relacionadas