Solicitudes lentas en el servidor local de Flask


87

Estoy empezando a jugar con Flask en un servidor local y me doy cuenta de que los tiempos de solicitud / respuesta son mucho más lentos de lo que creo que deberían ser.

Un simple servidor como el siguiente tarda cerca de 5 segundos en responder.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "index"

if __name__ == "__main__":
    app.run()

¿Algunas ideas? ¿O es así como es el servidor local?


No es el servidor local, pero podría tener que ver con otras aplicaciones que se ejecutan en segundo plano, ¿en qué sistema operativo está ejecutando esto?
gabeio

Estoy ejecutando OS X 10.7 en un i7 iMac
Meroon

1
No debería tomar tanto tiempo para sus respuestas, pero en realidad me he metido con el frasco antes sin éxito, le recomendaría a Bottlepy . Aunque aún verifique sus procesos en segundo plano, es posible que tenga una versión anterior de su servidor ejecutándose en segundo plano que se haga cargo de su python y provoque sus respuestas lentas. También podría ser su navegador, ¿esto sucede en Chrome y Safari?
gabeio

2
La respuesta de @ Meroon fue correcta para mí. Sin embargo, en lugar de cambiar la configuración del host: ¿Puedo recomendar simplemente usar 127.0.0.1 en lugar de localhost? Eso resolvió el problema sin cambiar la configuración del sistema.
David Bernat

Respuestas:


93

Ok, lo descubrí. Parece ser un problema con Werkzeug y los sistemas operativos que admiten ipv6.

Desde el sitio de Werkzeug http://werkzeug.pocoo.org/docs/serving/ :

En los sistemas operativos que admiten ipv6 y lo tienen configurado, como los sistemas Linux modernos, OS X 10.4 o superior, así como Windows Vista, algunos navegadores pueden ser terriblemente lentos si acceden a su servidor local. La razón de esto es que a veces “localhost” está configurado para estar disponible tanto en socktes ipv4 como ipv6 y algunos navegadores intentarán acceder primero a ipv6 y luego a ivp4.

Entonces, la solución es deshabilitar ipv6 desde el localhost comentando la siguiente línea de mi archivo de hosts:

::1             localhost 

Una vez que hago esto, los problemas de latencia desaparecen.

Realmente estoy investigando Flask y me alegro de que no sea un problema con el marco. Sabía que no podía ser.



¡muchas gracias! ¡de repente, las pruebas de desarrollo son rápidas y receptivas! mi única pregunta: como el archivo de hosts de Mac indica que eliminar localhost podría afectar las operaciones de mi Mac, me pregunto si se refiere a esta línea (o la que simplemente ubica localhost en 127.0.0.1
David B.

en mi sistema Windows 10 en el archivo de hosts ambas entradas (ip4 e ip6) están comentadas; son resueltos por el sistema DNS. Obtuve un gran aumento de velocidad cuando ejecuté el servidor en "127.0.0.1" en lugar de "localhost" (de 2.0 a 0.003 segundos para llamadas simples)
Lars

¡Gracias por esta respuesta! Aunque mi situación era un poco diferente (corriendo nose2 contra aiosmtpd), su respuesta me dio una pista: ¡cuando desactivo IPv6 en mi computadora portátil con Windows 10 acelera cosas como 10x o 100x!
pepoluan

87

Agregue "hilo = True" como argumento a app.run (), como se sugiere aquí: http://arusahni.net/blog/2013/10/flask-multithreading.html

Por ejemplo: app.run(host="0.0.0.0", port=8080, threaded=True)

La solución de desactivación de ipv6 no funcionó para mí, pero esto sí.


5
Pasar --threadeda mi manage.pyuso Flask-Scripttambién funcionó.
Snorfalorpagus

7
Para aquellos que lo "arreglan" habilitando subprocesos, ¡estén advertidos! En este caso, el retraso se debió a que la solicitud anterior no se cerró correctamente, por lo que ahora solo se apilan muchos hilos .
kbtz

Gracias, señor, por hacer que mi host local funcione increíblemente rápido.
benjaminz

@snolflake: ¿Hay alguna forma de saber si las solicitudes no se están cerrando correctamente?
Kylotan

1
Desde la línea de comando que utilicé flask run --with-threadsque resolvió mi problema.
arno_v

13

La solución de @ sajid-siddiqi es técnicamente correcta, pero tenga en cuenta que el servidor WSGI incorporado en Werkzeug (que está empaquetado en Flask y para lo que se usa app.run()) es solo de un solo subproceso.

Instale un servidor WSGI para poder manejar el comportamiento de subprocesos múltiples. Investigué un montón sobre el rendimiento de varios servidores WSGI . Sus necesidades pueden variar, pero si todo lo que está usando es Flask , le recomendaría uno de los siguientes servidores web.

Actualización (2020-07-25): Parece que gevent comenzó a admitir python3 hace 5 años, poco después de que comenté que no era así, por lo que puede usar gevent ahora.

gevent

Puede instalar gevent a través de pip con el comando pip install gevento pip3 con el comando pip3 install gevent. Las instrucciones sobre cómo modificar su código en consecuencia están aquí: https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

yo

gevent es mejor, pero de todos los puntos de referencia que he analizado que involucran pruebas en el mundo real, meinheld parece ser el servidor WSGI más sencillo y simplista . (También puede echar un vistazo a uWSGI si no le importa más configuración).

También puede instalar meinheld a través de pip3 con el comando pip3 install meinheld. A partir de ahí, mire la muestra proporcionada en la fuente de meinheld para integrar Flask : https://github.com/mopemope/meinheld/blob/master/example/flask_sample.py

* NOTA: Por mi uso de PyCharm , la línea se from meinheld import serverresalta como un error, pero el servidor se ejecutará, por lo que puede ignorar el error.


Tuve problemas importantes de rendimiento con Flask, incluso las solicitudes más simples tardaban aproximadamente 0,5 segundos en completarse. Acabo de cambiar a gevent y todo funciona perfectamente, ¡gracias!
Gronostaj

7

En lugar de llamar a http://localhost:port/endpointllamar http://127.0.0.1:port/endpoint. Esto eliminó el retraso inicial de 500 ms para mí.


para mí, eliminó algo como 3 segundos (cambié de 0.0.0.0 a 127.0.0.1). ¿Alguien puede explicar por qué y cómo funciona?
Rotkiv

¿Por qué, en nombre de Dios, funciona esto? Pasó de 2,06 segundos a 0,002 segundos. El navegador puede usar localhost sin problemas, pero las solicitudes.get en localhost tardan 2 segundos en resolverse.
Xevion

7

Mi problema se resolvió con "threadded = True", pero quiero dar algunos antecedentes para distinguir mi problema de otros para los que esto puede no ser suficiente.

  1. Mi problema solo surgió al ejecutar Flask con python3. Al cambiar a python2, ya no tuve este problema.
  2. Mi problema se manifestó solo al acceder a la API con Chrome, momento en el que Chrome mostró la pantalla esperada, pero todo lo demás se colgó (curl, ffx, etc.) hasta que recargué o cerré la pestaña de Chrome, momento en el que todo lo demás estaba esperando alrededor devolvió un resultado.

Mi mejor suposición es que Chrome estaba tratando de mantener la sesión abierta y Flask estaba bloqueando las solicitudes posteriores. Tan pronto como se detuvo o restableció la conexión de Chrome, se procesó todo lo demás.

En mi caso, el hilo lo solucionó. Por supuesto, ahora estoy revisando algunos de los enlaces que otros han proporcionado para asegurarme de que no causen ningún otro problema.


4

threaded=Truefunciona para mí, pero finalmente descubrí que el problema se debe a foxyproxy en Firefox. Dado que cuando la aplicación del matraz se ejecuta en localhost, se produce una respuesta lenta si

  • foxyproxy está habilitado en firefox

la respuesta lenta no sucederá si

  • foxyproxy está deshabilitado en firefox

  • acceder al sitio web utilizando otros navegadores

La única solución que encontré es deshabilitar foxyproxy, intenté agregar localhost a la lista negra de proxy y ajustar la configuración, pero ninguno de ellos funcionó.


2

Usé la respuesta de Miheko para resolver mi problema.

::1 localhostya estaba comentado en mi archivo de hosts y la configuración Threaded=trueno funcionó para mí. Cada solicitud de REST tardaba 1 segundo en procesarse en lugar de ser instantánea.

Estoy usando Python 3.6, y conseguí que el matraz fuera rápido y respondiera a las solicitudes de REST al hacer que el matraz usara gevent como su WSGI.

Para usar gevent, instálelo con pip install gevent

Posteriormente, usé https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41 para configurar el matraz para usar gevent.

En caso de que el enlace no funcione, estas son las partes importantes del script:

from flask import Flask, Response
from gevent.pywsgi import WSGIServer
from gevent import monkey

# need to patch sockets to make requests async
# you may also need to call this before importing other packages that setup ssl
monkey.patch_all()

app = Flask(__name__) 


# define some REST endpoints... 

def main():

    # use gevent WSGI server instead of the Flask
    # instead of 5000, you can define whatever port you want.
    http = WSGIServer(('', 5000), app.wsgi_app) 

    # Serve your application
    http.serve_forever()


if __name__ == '__main__':
    main()

threadded = True no funciona para (usando python 3.6.7 y cartero), obtengo VersionConflict: (greenlet 0.4.13 (c: \ anaconda3 \ lib \ site-packages), Requirement.parse ('greenlet> = 0.4. 14; platform_python_implementation == "CPython" ')), ¿puedo saber cómo resolver esto? Gracias
Hanzgs

0

Recibí este error cuando me ejecutaba en hosts distintos a los demás localhost, por lo que, para algunos, diferentes problemas subyacentes pueden presentar los mismos síntomas.

Cambié la mayoría de las cosas que he estado usando a Tornado y, anecdóticamente, me ayudó mucho. He tenido algunas cargas de página lentas, pero las cosas parecen en general más receptivas. Además, es muy anecdótico, pero parece que me doy cuenta de que Flask solo se ralentizará con el tiempo, pero Flask + Tornado menos. Me imagino usar Apache y mod_wsgiharía las cosas aún mejor, pero Tornado es realmente simple de configurar (ver http://flask.pocoo.org/docs/deploying/others/ ).

(Además, una pregunta relacionada: la aplicación Flask se cuelga ocasionalmente )


0

Tuve una solución diferente aquí. Acabo de eliminar todo .pycdel directorio del servidor y lo inicié de nuevo. Por cierto, localhost ya estaba comentado en mi archivo de hosts (Windows 8).

El servidor estuvo congelado todo el tiempo y ahora funciona bien de nuevo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.