Puis-je servir plusieurs clients en utilisant uniquement Flask app.run () en tant que autonome?

202

Je sais que je peux lier Flask à Apache ou à d'autres serveurs Web. Mais, je pensais à exécuter Flask en tant que serveur autonome servant simultanément plusieurs clients.

Est-ce possible? Dois-je gérer la génération de plusieurs threads et les gérer?

ATOzTOA
la source

Réponses:

295

flask.Flask.runaccepte des arguments de mot clé supplémentaires ( **options) qu'il transmet à werkzeug.serving.run_simple- deux de ces arguments sont threaded(un booléen) et processes(que vous pouvez définir sur un nombre supérieur à un pour que werkzeug génère plusieurs processus pour gérer les demandes).

threadedpar défaut à Truepartir de Flask 1.0, donc pour les dernières versions de Flask, le serveur de développement par défaut pourra servir plusieurs clients simultanément par défaut. Pour les anciennes versions de Flask, vous pouvez explicitement passer threaded=Truepour activer ce comportement.

Par exemple, vous pouvez faire

if __name__ == '__main__':
    app.run(threaded=True)

pour gérer plusieurs clients à l'aide de threads d'une manière compatible avec les anciennes versions de Flask, ou

if __name__ == '__main__':
    app.run(threaded=False, processes=3)

pour dire à Werkzeug de générer trois processus pour gérer les demandes entrantes, ou tout simplement

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

pour gérer plusieurs clients à l'aide de threads si vous savez que vous utiliserez Flask 1.0 ou une version ultérieure.

Cela étant dit, Werkzeug serving.run_simpleencapsule le wsgirefpackage de la bibliothèque standard - et ce package contient une implémentation de référence de WSGI, pas un serveur Web prêt pour la production. Si vous prévoyez d'utiliser Flask en production (en supposant que "production" n'est pas une application interne à faible trafic avec pas plus de 10 utilisateurs simultanés), assurez-vous de la placer derrière un vrai serveur Web (voir la section des documents de Flask intitulée Options de déploiement pour certaines méthodes suggérées).

Sean Vieira
la source
2
Et si je regarde un maximum de 100 utilisateurs? Puis-je simplement l'attribuer processes=100et en être satisfait? Dans mon cas, je n'ai besoin que de fichiers statiques, pas de méthodes HTTP Post. Mon exigence est, je veux exécuter tous les threads Flask dans le cadre de mon application parent, afin qu'ils puissent tous partager des variables.
ATOzTOA
4
Rires - @ATOzTOA - non, ce serait probablement assez contre-productif (les processus sont relativement chers, et à moins que vous ne fassiez beaucoup de travail dans chaque demande, il n'y a aucune raison pour que 4 ou 8 processus ne soient pas suffisants). Cela dit, si vous affichez uniquement du contenu statique, vous feriez mieux avec un serveur optimisé pour cela (Apache, ngnix, IIS).
Sean Vieira
2
En outre, vous ne devriez généralement pas avoir besoin de partager des variables entre les demandes - si vous le faites, vous devrez soit vous limiter à un processus ou utiliser une communication hors bande (Redis, une base de données, le système de fichiers, etc.) donc que chacun de vos processus reste synchronisé.
Sean Vieira
3
@ATOzTOA - si vous ne pouvez pas faire tourner un meilleur serveur, alors je lui donnerais juste un tourbillon et je verrais ce qui se passe. S'il ne fonctionne pas bien sous charge, vous pouvez le déployer derrière un autre serveur Web.
Sean Vieira
2
@ATOzTOA, concernant votre question sur la raison pour laquelle vous ne pouvez pas spécifier 'threaded' et 'processus' en même temps, cf le code ici: werkzeug.readthedocs.org/en/latest/_modules/werkzeug/serving
pyrho
62

L'utilisation du simple à app.run()partir de Flask crée un serveur synchrone unique sur un seul thread capable de servir un seul client à la fois. Il est destiné à être utilisé dans des environnements contrôlés avec une faible demande (développement, débogage, par exemple) pour cette raison.

Générer des threads et les gérer vous-même ne vous mènera probablement pas très loin non plus, à cause de Python GIL .

Cela dit, vous avez encore de bonnes options. Gunicorn est un serveur WSGI solide et facile à utiliser qui vous permettra de générer plusieurs travailleurs (processus séparés, donc pas de soucis GIL), et est même livré avec des travailleurs asynchrones qui accéléreront votre application (et la rendront plus sécurisée) avec peu à aucun travail de votre part (surtout avec Flask).

Pourtant, même Gunicorn ne devrait probablement pas être directement exposé publiquement. En production, il devrait être utilisé derrière un serveur HTTP plus robuste; nginx a tendance à bien aller avec Gunicorn et Flask.

Ryan Artecona
la source
17
pas assez. Gunicorn est en python, nginx ne l'est pas. ce n'est pas ainsi que vous les utiliseriez. Gunicorn vous permettrait d'exécuter votre application au gunicorn app:app 127.0.0.1:8080lieu de python app.py. Nginx agirait en tant que service public qui expose votre application privée exécutée par Gunicorn (un proxy inverse) , cachant toutes sortes de détails d'implémentation HTTP de niveau inférieur, servant peut-être directement des fichiers statiques, etc.
Ryan Artecona
Flask avec app.run (threaded = True) fonctionne très bien sur Apache2 en utilisant mod_wsgi flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi
MortenB