Flask
Implementando la aplicación Flask usando el servidor web uWSGI con Nginx
Buscar..
Usando uWSGI para ejecutar una aplicación matraz
El servidor werkzeug
incorporado ciertamente no es adecuado para ejecutar servidores de producción. La razón más obvia es el hecho de que el servidor werkzeug
es de un solo hilo y, por lo tanto, solo puede manejar una solicitud a la vez.
Debido a esto, queremos usar el servidor uWSGI para servir nuestra aplicación en su lugar. En este ejemplo instalaremos uWSGI y ejecutaremos una aplicación de prueba simple con él.
Instalando uWSGI :
pip install uwsgi
Es tan simple como eso. Si no está seguro de la versión de python que utiliza su pip, hágala explícita:
python3 -m pip install uwsgi # for python3
python2 -m pip install uwsgi # for python2
Ahora vamos a crear una aplicación de prueba 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
En el matraz, el nombre convencional para la aplicación es app
pero uWSGI busca la application
por defecto. Es por eso que creamos un alias para nuestra aplicación en la última línea.
Ahora es el momento de ejecutar la aplicación:
uwsgi --wsgi-file app.py --http :5000
Debería ver el mensaje "Hola uWSGI ..." apuntando su navegador a localhost:5000
Para no escribir el comando completo cada vez que creamos un archivo uwsgi.ini
para almacenar esa configuración:
uwsgi.ini
[uwsgi]
http = :9090
wsgi-file = app.py
single-interpreter = true
enable-threads = true
master = true
Las opciones de wsgi-file
http
y wsgi-file
son las mismas que en el comando manual. Pero hay tres opciones más:
single-interpreter
: se recomienda activar esto porque podría interferir con la siguiente opciónenable-threads
: esto debe estar activado si está utilizando subprocesos adicionales en su aplicación. No los usamos ahora, pero ahora no tenemos que preocuparnos por eso.master
: el modo maestro debe habilitarse por varias razones
Ahora podemos ejecutar la aplicación con este comando:
uwsgi --ini uwsgi.ini
Instalando nginx y configurándolo para uWSGI
Ahora queremos instalar nginx para servir nuestra aplicación.
sudo apt-get install nginx # on debian/ubuntu
Luego creamos una configuración para nuestro sitio 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;
}
}
Esto le indica a nginx que escuche en el puerto 80 (predeterminado para http) y sirva algo en la ruta raíz ( /
). Allí le decimos a nginx que simplemente actúe como un proxy y pase cada solicitud a un socket llamado flask.sock
ubicado en /tmp/
.
Vamos a habilitar el sitio:
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/flaskconfig .
Es posible que desee eliminar la configuración predeterminada si está habilitada:
# inside /etc/sites-enabled
sudo rm default
Luego reinicie nginx:
sudo service nginx restart
Apunte su navegador a localhost
y verá un error: 502 Bad Gateway
.
Esto significa que nginx está activo y funcionando pero falta el zócalo. Así que vamos a crear eso.
Vuelva a su archivo uwsgi.ini
y ábralo. Luego agrega estas líneas:
socket = /tmp/flask.sock
chmod-socket = 666
La primera línea le dice a uwsgi que cree un socket en la ubicación dada. El socket se utilizará para recibir solicitudes y enviar las respuestas. En la última línea permitimos que otros usuarios (incluido nginx) puedan leer y escribir desde ese socket.
Vuelva a iniciar uwsgi con uwsgi --ini uwsgi.ini
. Ahora apunte su navegador de nuevo a localhost
y verá nuevamente el saludo "Hola, uWSGI".
Tenga en cuenta que todavía puede ver la respuesta en localhost:5000
porque uWSGI ahora sirve la aplicación a través de http y el socket. Así que vamos a deshabilitar la opción http en el archivo ini
http = :5000 # <-- remove this line and restart uwsgi
Ahora solo se puede acceder a la aplicación desde nginx (o leer ese socket directamente :)).
Habilitar la transmisión desde el matraz
Flask tiene esa característica que le permite transmitir datos desde una vista mediante el uso de generadores.
Vamos a cambiar el archivo app.py
- añadir
from flask import Response
- agregar
from datetime import datetime
- añadir
from time import sleep
- crear una nueva vista:
@app.route("/time/")
def time():
def streamer():
while True:
yield "<p>{}</p>".format(datetime.now())
sleep(1)
return Response(streamer())
Ahora abra su navegador en localhost/time/
. El sitio se cargará para siempre porque nginx espera hasta que se complete la respuesta. En este caso, la respuesta nunca estará completa porque enviará la fecha y hora actuales para siempre.
Para evitar que nginx espere, debemos agregar una nueva línea a la configuración.
Edite /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 línea uwsgi_buffering off;
le dice a nginx que no espere hasta que se complete una respuesta.
Reinicie nginx: sudo service nginx restart
y observe localhost/time/
again.
Ahora verás que a cada segundo aparece una nueva línea.
Configure la aplicación Flask, uWGSI, Nginx - Plantilla de caldera de configuraciones de servidor (predeterminado, proxy y caché)
Esta es una parte de la configuración que se obtiene del tutorial de DigitalOcean de Cómo Servir las Aplicaciones de Flask con uWSGI y Nginx en Ubuntu 14.04
y algunos recursos git útiles para servidores nginx.
Aplicación del matraz
Este tutorial asume que usas Ubuntu.
- busque
var/www/
folder. - Crea tu carpeta de aplicaciones web
mkdir myexample
-
cd myexample
opcional Es posible que desee configurar un entorno virtual para implementar aplicaciones web en el servidor de producción.
sudo pip install virtualenv
para instalar el entorno virtual.
virtualenv myexample
para configurar el entorno virtual para su aplicación.
source myprojectenv/bin/activate
para activar su entorno. Aquí instalarás todos los paquetes de python.
final opcional pero recomendado
Configurar frasco y puerta de enlace uWSGI
Instalar matraz y puerta de enlace uSWGI:
pip install uwsgi flask
Ejemplo de aplicación matraz en 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')
Cree un archivo para comunicarse entre su aplicación web y el servidor web: interfaz de puerta de enlace [ https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface]
nano wsgi.py
luego importe su módulo de aplicación web y hágalo funcionar desde el punto de entrada de la puerta de enlace.
from myexample import application
if __name__ == "__main__":
application.run()
Para probar uWSGI:
uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi
Para configurar uWSGI:
Crear un archivo de configuración
.ini
nano myexample.ini
Configuración básica para gateway 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
Opcional si está usando env virtual . Puede deactivate
su entorno virtual.
Configuración de Nginx Vamos a utilizar nginx como:
- servidor predeterminado para pasar la solicitud al socket, utilizando el protocolo uwsgi
- servidor proxy delante del servidor predeterminado
- servidor de caché para almacenar en caché las solicitudes exitosas (como ejemplo, es posible que desee almacenar en caché las solicitudes GET si su aplicación web)
Localice su directorio de sites-available
y cree un archivo de configuración para su aplicación:
sudo nano /etc/nginx/sites-available/myexample
Agregue el siguiente bloque, en comentarios lo que hace:
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;
}
}
Finalmente, vincule el archivo al directorio de sites-enabled
. Para obtener una explicación de los sitios disponibles y habilitados, consulte la respuesta: [ http://serverfault.com/a/527644]
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Ya has terminado con nginx. Sin embargo, es posible que desee revisar esta preciosa plantilla de caldera: [ https://github.com/h5bp/server-configs-nginx]
Muy útil para el ajuste fino.
Ahora prueba Nginx:
sudo nginx -t
Lanzar Nginx:
sudo service nginx restart
Automatice Ubuntu para iniciar uWSGI Lo último es hacer que Ubuntu inicie la puerta de enlace wsgi comunicándose con su aplicación, de lo contrario debería hacerlo manualmente.
- Localice el directorio para los scripts de inicialización en Ubuntu y cree un nuevo script:
sudo nano /etc/init/myexample.conf
Agregue el siguiente bloque, comentarios en línea para explicar lo que hace
# 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
Ahora puedes activar tu script: sudo start myexample