Déploiement de l'application Flask à l'aide du serveur Web uWSGI avec Nginx
Activer le streaming depuis le flacon
Flask a cette fonctionnalité qui vous permet de diffuser des données à partir d’une vue en utilisant des générateurs.
Modifions le fichier app.py
-
ajouter
à partir de la réponse d'importation de flacon
-
ajouter
de datetime import datetime
-
ajouter
à partir de l'heure d'importation du sommeil
-
créer une nouvelle vue :
@app.route("/time/") def time(): def streamer(): while True: yield “
{}
".format(datetime.now()) sleep(1)return Response(streamer())
Ouvrez maintenant votre navigateur à localhost/time/
. Le site se chargera indéfiniment car nginx attend que la réponse soit complète. Dans ce cas, la réponse ne sera jamais complète car elle enverra la date et l’heure actuelles pour toujours.
Pour empêcher nginx d’attendre, nous devons ajouter une nouvelle ligne à la configuration.
Modifier /etc/nginx/sites-available/flaskconfig
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/flask.sock;
uwsgi_buffering off; # <-- this line is new
}
}
La ligne uwsgi_buffering off;
indique à nginx de ne pas attendre qu’une réponse soit terminée.
Redémarrez nginx : sudo service nginx restart
et regardez à nouveau localhost/time/
.
Maintenant, vous verrez que chaque seconde une nouvelle ligne apparaît.
Configurer l’application Flask, uWGSI, Nginx - Modèle de chaudière de configurations de serveur (par défaut, proxy et cache)
Il s’agit d’un portage de la configuration provenant du didacticiel de DigitalOcean sur [* Comment servir les applications Flask avec uWSGI et Nginx sur Ubuntu 14.04 *] [1]
et quelques ressources git utiles pour les serveurs nginx.
Application en flacon
Ce tutoriel suppose que vous utilisez Ubuntu.
- Localisez le dossier
var/www/
. - Créez votre dossier d’application Web
mkdir myexample
cd monexemple
facultatif Vous souhaiterez peut-être configurer un environnement virtuel pour déployer des applications Web sur le serveur de production.
sudo pip install virtualenv
pour installer l’environnement virtuel.
virtualenv myexample
pour configurer un environnement virtuel pour votre application.
source myprojectenv/bin/activate
pour activer votre environnement. Ici, vous allez installer tous les packages Python.
fin facultatif mais recommandé
Configurer le flacon et la passerelle uWSGI
Installez le flacon et la passerelle uSWGI :
pip install uwsgi flask
Exemple d’application flask dans myexample.py :
from flask import Flask
application = Flask(__name__)
@application.route("/")
def hello():
return "<h1>Hello World</h1>"
if __name__ == "__main__":
application.run(host='0.0.0.0')
Créer un fichier pour communiquer entre votre application Web et le serveur Web : interface de passerelle [https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface]
nano wsgi.py
puis importez votre module webapp et faites-le fonctionner à partir du point d’entrée de la passerelle.
from myexample import application
if __name__ == "__main__":
application.run()
Pour tester uWSGI :
uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi
Pour configurer uWSGI :
-
Créez un fichier de configuration
.ini
nano myexample.ini
-
Configuration de base pour la passerelle uWSGI
include header for using uwsgi
[uwsgi]
point it to your python module wsgi.py
module = wsgi
tell uWSGI to start a master node to serve requests
master = true
spawn number of processes handling requests
processes = 5
use a Unix socket to communicate with Nginx. Nginx will pass connections to uWSGI through a socket, instead of using ports. This is preferable because Nginx and uWSGI stays on the same machine.
socket = myexample.sock
ensure file permission on socket to be readable and writable
chmod-socket = 660
clean the socket when processes stop
vacuum = true
use die-on-term to communicate with Ubuntu versions using Upstart initialisations: see:
http://uwsgi-docs.readthedocs.io/en/latest/Upstart.html?highlight=die%20on%20term
die-on-term = true
facultatif si vous utilisez un environnement virtuel Vous pouvez “désactiver” votre environnement virtuel.
Configuration Nginx Nous allons utiliser nginx comme :
- serveur par défaut pour transmettre la requête au socket, en utilisant le protocole uwsgi
- serveur proxy devant le serveur par défaut
- serveur de cache pour mettre en cache les requêtes réussies (par exemple, vous voudrez peut-être mettre en cache les requêtes GET si votre application Web)
Localisez votre répertoire “sites-available” et créez un fichier de configuration pour votre application :
sudo nano /etc/nginx/sites-available/myexample
Ajoutez le bloc suivant, dans les commentaires ce qu’il fait :
server {
# setting up default server listening to port 80
listen 8000 default_server;
server_name myexample.com; #you can also use your IP
# specify charset encoding, optional
charset utf-8;
# specify root of your folder directory
root /var/www/myexample;
# specify locations for your web apps.
# here using /api endpoint as example
location /api {
# include parameters of wsgi.py and pass them to socket
include uwsgi_params;
uwsgi_pass unix:/var/www/myexample/myexample.sock;
}
}
# Here you will specify caching zones that will be used by your virtual server
# Cache will be stored in /tmp/nginx folder
# ensure nginx have permissions to write and read there!
# See also:
# http://nginx.org/en/docs/http/ngx_http_proxy_module.html
proxy_cache_path /tmp/nginx levels=1:2 keys_zone=my_zone:10m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
# set up the virtual host!
server {
listen 80 default_server;
# Now www.example.com will listen to port 80 and pass request to http://example.com
server_name www.example.com;
# Why not caching responses
location /api {
# set up headers for caching
add_header X-Proxy-Cache $upstream_cache_status;
# use zone specified above
proxy_cache my_zone;
proxy_cache_use_stale updating;
proxy_cache_lock on;
# cache all responses ?
# proxy_cache_valid 30d;
# better cache only 200 responses :)
proxy_cache_valid 200 30d;
# ignore headers to make cache expire
proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
# pass requests to default server on port 8000
proxy_pass http://example.com:8000/api;
}
}
Enfin, liez le fichier au répertoire sites-enabled
.
Pour une explication des sites disponibles et activés, voir la réponse :
[http://serverfault.com/a/527644]
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Vous avez maintenant terminé avec nginx. Cependant, vous voudrez peut-être consulter ce modèle de chaudière très précieux : [https://github.com/h5bp/server-configs-nginx]
Très utile pour un réglage fin.
Testez maintenant Nginx :
sudo nginx -t
Lancez Nginx :
sudo service nginx restart
** Automatisez Ubuntu pour démarrer uWSGI ** La dernière chose à faire est de faire en sorte qu’Ubuntu démarre la passerelle wsgi communiquant avec votre application, sinon vous devriez le faire manuellement.
- Localisez le répertoire des scripts d’initialisation dans Ubuntu et créez un nouveau script :
sudo nano /etc/init/monexemple.conf
-
Ajoutez le bloc suivant, des commentaires en ligne pour expliquer ce qu’il fait
# description for the purpose of this script description "uWSGI server instance configured to serve myproject" # Tell to start on system runtime 2, 3, 4, 5. Stop at any other level (0,1,6). # Linux run levels: [http://www.debianadmin.com/debian-and-ubuntu-linux-run-levels.html] start on runlevel [2345] stop on runlevel [!2345] # Set up permissions! "User" will be the username of your user account on ubuntu. setuid user # Allow www-data group to read and write from the socket file. # www-data is normally the group Nginx and your web applications belong to. # you may have all web application projects under /var/www/ that belongs to www-data group setgid www-data # tell Ubunutu which environment to use. # This is the path of your virtual environment: python will be in this path if you installed virtualenv. Otherwise, use path of your python installation env PATH=/var/www/myexample/myexample/bin # then tell to Ubuntu to change and locate your web application directory chdir /var/www/myexample # finally execute initialisation script, that load your web app myexample.py exec uwsgi --ini myexample.ini
Vous pouvez maintenant activer votre script : sudo start monexemple
[1] : https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-14-04
Utiliser uWSGI pour exécuter une application flask
Le serveur werkzeug
intégré n’est certainement pas adapté à l’exécution de serveurs de production. La raison la plus évidente est le fait que le serveur werkzeug
est monothread et ne peut donc traiter qu’une requête à la fois.
Pour cette raison, nous souhaitons utiliser le serveur uWSGI pour servir notre application à la place. Dans cet exemple, nous allons installer uWSGI et exécuter une application de test simple avec.
Installation de uWSGI :
pip install uwsgi
C’est aussi simple que ça. Si vous n’êtes pas sûr de la version de python que votre pip utilise, précisez-le :
python3 -m pip install uwsgi # for python3
python2 -m pip install uwsgi # for python2
Créons maintenant une application de test simple :
app.py
from flask import Flask
from sys import version
app = Flask(__name__)
@app.route("/")
def index():
return "Hello uWSGI from python version: <br>" + version
application = app
Dans flask, le nom conventionnel de l’application est “app”, mais uWSGI recherche “application” par défaut. C’est pourquoi nous créons un alias pour notre application dans la dernière ligne.
Il est maintenant temps d’exécuter l’application :
uwsgi --wsgi-file app.py --http :5000
Vous devriez voir le message “Hello uWSGI …” en pointant votre navigateur vers localhost:5000
Afin de ne pas taper la commande complète à chaque fois, nous allons créer un fichier uwsgi.ini
pour stocker cette configuration :
uwsgi.ini
[uwsgi]
http = :9090
wsgi-file = app.py
single-interpreter = true
enable-threads = true
master = true
Les options http
et wsgi-file
sont les mêmes que dans la commande manuelle. Mais il y a trois autres options :
-
single-interpreter
: il est recommandé de l’activer car cela pourrait interférer avec l’option suivante -
enable-threads
: cette option doit être activée si vous utilisez des threads supplémentaires dans votre application. Nous ne les utilisons pas pour le moment, mais maintenant nous n’avons plus à nous en soucier. -
master
: le mode maître doit être activé pour [diverses raisons] (http://stackoverflow.com/questions/20197259/what-is-uwsgi-master-mode)
Nous pouvons maintenant exécuter l’application avec cette commande :
uwsgi --ini uwsgi.ini
Installation de nginx et configuration pour uWSGI
Nous voulons maintenant installer nginx pour servir notre application.
sudo apt-get install nginx # on debian/ubuntu
Ensuite, nous créons une configuration pour notre site Web
cd /etc/nginx/site-available # go to the configuration for available sites
# create a file flaskconfig with your favourite editor
flaskconfig
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/flask.sock;
}
}
Cela indique à nginx d’écouter sur le port 80 (par défaut pour http) et de servir quelque chose au chemin racine (/
). Là, nous disons à nginx d’agir simplement comme un proxy et de transmettre chaque requête à un socket appelé flask.sock
situé dans /tmp/
.
Activons le site :
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/flaskconfig .
Vous voudrez peut-être supprimer la configuration par défaut si elle est activée :
# inside /etc/sites-enabled
sudo rm default
Redémarrez ensuite nginx :
sudo service nginx restart
Pointez votre navigateur vers localhost
et vous verrez une erreur : 502 Bad Gateway
.
Cela signifie que nginx est opérationnel mais que le socket est manquant. Alors créons ça.
Revenez à votre fichier uwsgi.ini
et ouvrez-le. Ajoutez ensuite ces lignes :
socket = /tmp/flask.sock
chmod-socket = 666
La première ligne indique à uwsgi de créer un socket à l’emplacement donné. Le socket sera utilisé pour recevoir les requêtes et renvoyer les réponses. Dans la dernière ligne, nous autorisons les autres utilisateurs (y compris nginx) à pouvoir lire et écrire à partir de ce socket.
Redémarrez uwsgi avec uwsgi --ini uwsgi.ini
. Maintenant, pointez à nouveau votre navigateur sur localhost
et vous verrez à nouveau le message d’accueil “Hello uWSGI”.
Notez que vous pouvez toujours voir la réponse sur localhost:5000
car uWSGI sert maintenant l’application via http et le socket. Désactivons donc l’option http dans le fichier ini
http = :5000 # <-- remove this line and restart uwsgi
Désormais, l’application n’est accessible qu’à partir de nginx (ou en lisant directement ce socket :) ).