Demandes lentes sur le serveur Flask local

87

Je commence à peine à jouer avec Flask sur un serveur local et je remarque que les temps de demande / réponse sont beaucoup plus lents que je ne le pense.

Un simple serveur comme celui-ci prend près de 5 secondes pour répondre.

from flask import Flask

app = Flask(__name__)

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

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

Des idées? Ou est-ce simplement ainsi que le serveur local est?

Meroon
la source
Ce n'est pas le serveur local mais cela pourrait avoir à voir avec d'autres applications fonctionnant en arrière-plan sur quel système d'exploitation exécutez-vous cela?
gabeio
Je tourne sous OS X 10.7 sur un iMac i7
Meroon
1
Cela ne devrait pas prendre autant de temps pour vos réponses, mais j'ai déjà joué avec Flask avant sans succès, je conseillerais Bottlepy . Bien que vous puissiez toujours vérifier vos processus en arrière-plan, vous pouvez avoir une ancienne version de votre serveur en arrière-plan prenant le relais de votre python et provoquant des réponses lentes. Cela pourrait aussi être votre navigateur dans Chrome & Safari?
gabeio
2
La réponse de @ Meroon était correcte pour moi. Plutôt que de changer les paramètres de l'hôte, cependant: puis-je recommander simplement d'utiliser 127.0.0.1 au lieu de localhost? Cela a résolu le problème sans changer la configuration du système.
David Bernat

Réponses:

93

Ok je l'ai compris. Cela semble être un problème avec Werkzeug et les systèmes d'exploitation prenant en charge ipv6.

Depuis le site Werkzeug http://werkzeug.pocoo.org/docs/serving/ :

Sur les systèmes d'exploitation qui prennent en charge ipv6 et l'ont configuré, tels que les systèmes Linux modernes, OS X 10.4 ou supérieur ainsi que Windows Vista, certains navigateurs peuvent être extrêmement lents s'ils accèdent à votre serveur local. La raison en est que parfois «localhost» est configuré pour être disponible sur les socktes ipv4 et ipv6 et certains navigateurs essaieront d'accéder d'abord à ipv6, puis à ivp4.

Le correctif consiste donc à désactiver ipv6 à partir de l'hôte local en commentant la ligne suivante de mon fichier d'hôtes:

::1             localhost 

Une fois que je fais cela, les problèmes de latence disparaissent.

Je creuse vraiment Flask et je suis content que ce ne soit pas un problème avec le framework. Je savais que ça ne pouvait pas être.

Meroon
la source
Merci beaucoup! tout à coup, les tests de développement sont rapides et réactifs! ma seule question: comme le fichier d'hôtes Mac indique que la suppression de l'hôte local pourrait affecter les opérations de mon Mac, je me demande s'il fait référence à cette ligne (ou à celle qui localise simplement localhost à 127.0.0.1
David B.
sur mon système Windows 10 dans le fichier hosts, les deux entrées (ip4 et ip6) sont commentées; ils sont résolus par le système DNS. J'ai eu une énorme augmentation de vitesse lorsque j'ai exécuté le serveur sur "127.0.0.1" au lieu de "localhost" (de 2,0 à 0,003 secondes pour des appels simples)
Lars
Merci pour cette réponse! Bien que ma situation soit un peu différente (exécuter nose2 contre aiosmtpd), votre réponse m'a donné un indice: lorsque je désactive IPv6 sur mon ordinateur portable Windows 10 accélère des choses comme 10x ou 100x !!
pepoluan
87

Ajoutez "threaded = True" comme argument à app.run (), comme suggéré ici: http://arusahni.net/blog/2013/10/flask-multithreading.html

Par exemple: app.run(host="0.0.0.0", port=8080, threaded=True)

La solution de désactivation d'ipv6 n'a pas fonctionné pour moi, mais cela a fonctionné.

Sajid Siddiqi
la source
5
Passer --threadedà mon manage.pyutilisation Flask-Scripta également fonctionné.
Snorfalorpagus
7
Pour ceux qui le «corrigent» en activant les threads, soyez prévenus! Dans ce cas, le retard était dû au fait que la demande précédente n'était pas fermée correctement, donc maintenant, il s'agit en fait d' empiler un grand nombre de threads .
kbtz
Merci monsieur d'avoir rendu mon hôte local extrêmement rapide.
benjaminz
@snolflake: Existe-t-il un moyen de savoir si les requêtes ne sont pas correctement fermées?
Kylotan
1
À partir de la ligne de commande que j'ai utilisée, flask run --with-threadsce qui a résolu mon problème.
arno_v
13

La solution de @ sajid-siddiqi est techniquement correcte, mais gardez à l'esprit que le serveur WSGI intégré à Werkzeug (qui est emballé dans Flask et à quoi il sert app.run()) n'est qu'à thread unique.

Installez un serveur WSGI pour pouvoir gérer le comportement multi-thread. J'ai fait un tas de recherches sur diverses performances du serveur WSGI . Vos besoins peuvent varier, mais si tout ce que vous utilisez est Flask , je vous recommande l'un des serveurs Web suivants.

Mise à jour (2020-07-25): Il semble que gevent a commencé à prendre en charge python3 il y a 5 ans, peu de temps après avoir commenté que ce n'était pas le cas, vous pouvez donc utiliser gevent maintenant.

Gevent

Vous pouvez installer gevent via pip avec la commande pip install geventou pip3 avec la commande pip3 install gevent. Les instructions pour modifier votre code en conséquence sont ici: https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

meinheld

gevent est meilleur, mais de tous les benchmarks que j'ai examinés et qui impliquent des tests dans le monde réel, meinheld semble être le serveur WSGI le plus simple et le plus simple . (Vous pouvez également jeter un oeil à uWSGI si cela ne vous dérange pas une configuration supplémentaire.)

Vous pouvez également installer meinheld via pip3 avec la commande pip3 install meinheld. À partir de là, regardez l'exemple fourni dans la source meinheld pour intégrer Flask : https://github.com/mopemope/meinheld/blob/master/example/flask_sample.py

* REMARQUE: De mon utilisation de PyCharm , la ligne est from meinheld import servermise en évidence comme une erreur, mais le serveur fonctionnera, vous pouvez donc ignorer l'erreur.

Mikeho
la source
J'ai eu des problèmes de performances majeurs avec Flask, même les demandes les plus simples prenaient environ 0,5 seconde pour se terminer. Je viens de passer à gevent et tout fonctionne parfaitement, merci!
gronostaj
7

Au lieu d'appeler, http://localhost:port/endpointappelez http://127.0.0.1:port/endpoint. Cela a supprimé le délai initial de 500 ms pour moi.

LangeTreeDorpie
la source
pour moi, il a supprimé quelque chose comme 3 secondes (j'ai déplacé le formulaire 0.0.0.0 à 127.0.0.1). Quelqu'un peut-il expliquer pourquoi et comment cela fonctionne?
Rotkiv
Pourquoi au nom des dieux cela fonctionne-t-il? Je suis passé de 2,06 secondes à 0,002 secondes. Le navigateur peut utiliser localhost sans problème, mais requests.get sur localhost prend 2 secondes à résoudre.
Xevion
7

Mon problème a été résolu par "threaded = True", mais je veux donner un peu de contexte pour distinguer mon problème des autres pour lesquels cela peut ne pas le faire.

  1. Mon problème n'est survenu que lors de l'exécution de Flask avec python3. En passant à python2, je n'ai plus eu ce problème.
  2. Mon problème ne s'est manifesté que lors de l'accès à l'API avec Chrome, à quel point Chrome a affiché l'écran attendu, mais tout le reste s'est bloqué (curl, ffx, etc.) jusqu'à ce que je recharge ou ferme l'onglet Chrome, auquel point tout le reste qui attendait autour a renvoyé un résultat.

Ma meilleure hypothèse est que Chrome essayait de garder la session ouverte et que Flask bloquait les demandes suivantes. Dès que la connexion depuis Chrome a été interrompue ou réinitialisée, tout le reste a été traité.

Dans mon cas, le filetage l'a corrigé. Bien sûr, je passe maintenant en revue certains des liens fournis par d'autres pour m'assurer que cela ne causera aucun autre problème.

ChePazzo
la source
4

threaded=Truefonctionne pour moi, mais j'ai finalement compris que le problème était dû à foxyproxy sur Firefox. Depuis que l'application flask s'exécute sur localhost, une réponse lente se produit si

  • foxyproxy est activé sur firefox

une réponse lente ne se produira pas si

  • foxyproxy est désactivé sur firefox

  • accéder au site Web en utilisant d'autres navigateurs

La seule solution que j'ai trouvée est de désactiver foxyproxy, j'ai essayé d'ajouter localhost à la liste noire du proxy et de modifier les paramètres, mais aucun d'entre eux n'a fonctionné.

Edward
la source
2

J'ai utilisé la réponse de Miheko pour résoudre mon problème.

::1 localhosta déjà été commenté sur mon fichier hosts, et le réglage Threaded=truene fonctionnait pas pour moi. Chaque requête REST prenait 1 seconde à traiter au lieu d'être instantanée.

J'utilise python 3.6 et j'ai fait en sorte que flask soit rapide et réactif aux demandes REST en faisant en sorte que flask utilise gevent comme WSGI.

Pour utiliser gevent, installez-le avec pip install gevent

Ensuite, j'ai utilisé https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41 pour configurer flask afin qu'il utilise gevent.

En cas de panne du lien, voici les parties importantes du 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()
Ali Mizan
la source
threaded = True ne fonctionne pas pour (en utilisant python 3.6.7 et postman), j'obtiens VersionConflict: (greenlet 0.4.13 (c: \ anaconda3 \ lib \ site-packages), Requirement.parse ('greenlet> = 0.4. 14; platform_python_implementation == "CPython" ')), puis-je savoir comment résoudre ce problème, merci
bloque le
0

J'ai eu cette erreur lors de l'exécution sur des hôtes autres que localhost, donc pour certains, différents problèmes sous-jacents peuvent présenter les mêmes symptômes.

J'ai changé la plupart des choses que j'utilisais pour Tornado et, de manière anecdotique, cela a aidé un montant. J'ai eu quelques chargements de pages lents, mais les choses semblent généralement plus réactives. Aussi, très anecdotique, mais je semble remarquer que Flask seul ralentira avec le temps, mais Flask + Tornado moins. J'imagine utiliser Apache et mod_wsgiaméliorerait encore les choses, mais Tornado est vraiment simple à installer (voir http://flask.pocoo.org/docs/deploying/others/ ).

(En outre, une question connexe: l' application Flask suspendue parfois )

gatoatigrado
la source
0

J'avais une solution différente ici. Je viens de tout supprimer .pycdu répertoire du serveur et je l'ai redémarré. À propos, localhost a déjà été commenté dans mon fichier hosts (Windows 8).

Le serveur gelait tout le temps et maintenant il fonctionne à nouveau correctement.

erickrf
la source