Ricerca…


Usando uWSGI per eseguire un'applicazione flask

Il server werkzeug integrato non è certamente adatto per l'esecuzione di server di produzione. La ragione più ovvia è il fatto che il server werkzeug è a thread singolo e quindi può gestire solo una richiesta alla volta.

Per questo motivo, vogliamo utilizzare uWSGI Server per servire la nostra applicazione. In questo esempio installeremo uWSGI ed eseguiremo una semplice applicazione di test.

Installare uWSGI :

pip install uwsgi

È così semplice. Se non sei sicuro della versione python che usi, pip lo rende esplicito:

python3 -m pip install uwsgi  # for python3
python2 -m pip install uwsgi  # for python2

Ora creiamo una semplice applicazione di test:

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

In flask il nome convenzionale dell'applicazione è app ma uWSGI cerca l' application per impostazione predefinita. Ecco perché creiamo un alias per la nostra app nell'ultima riga.

Ora è il momento di eseguire l'app:

uwsgi --wsgi-file app.py --http :5000

Dovresti vedere il messaggio "Hello uWSGI ..." puntando il tuo browser su localhost:5000

Per non digitare il comando completo ogni volta che creeremo un file uwsgi.ini per memorizzare quella configurazione:

uwsgi.ini

[uwsgi]
http = :9090
wsgi-file = app.py
single-interpreter = true
enable-threads = true
master = true

Le opzioni http e wsgi-file sono le stesse del comando manuale. Ma ci sono altre tre opzioni:

  • single-interpreter : si consiglia di attivare questa opzione perché potrebbe interferire con l'opzione successiva

  • enable-threads : questo deve essere attivato se si stanno utilizzando thread aggiuntivi nell'applicazione. Non li usiamo in questo momento ma ora non dobbiamo preoccuparcene.

  • master : la modalità Master dovrebbe essere abilitata per vari motivi

Ora possiamo eseguire l'app con questo comando:

uwsgi --ini uwsgi.ini

Installare nginx e configurarlo per uWSGI

Ora vogliamo installare nginx per servire la nostra applicazione.

sudo apt-get install nginx  # on debian/ubuntu

Quindi creiamo una configurazione per il nostro sito 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;
    }
}

Questo dice a nginx di ascoltare sulla porta 80 (predefinita per http) e di servire qualcosa nel percorso root ( / ). Qui diciamo a nginx di agire come un proxy e passare ogni richiesta a un socket chiamato flask.sock trova in /tmp/ .

Abilitiamo il sito:

cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/flaskconfig .

Potresti voler rimuovere la configurazione predefinita se è abilitata:

# inside /etc/sites-enabled
sudo rm default

Quindi riavvia nginx:

sudo service nginx restart

Indirizza il tuo browser su localhost e vedrai un errore: 502 Bad Gateway .

Ciò significa che nginx è attivo e funzionante, ma manca il socket. Quindi lasciamolo creare.

Torna al tuo file uwsgi.ini e aprilo. Quindi aggiungi queste righe:

socket = /tmp/flask.sock
chmod-socket = 666

La prima riga dice a uwsgi di creare un socket nella posizione specificata. Il socket verrà utilizzato per ricevere richieste e inviare le risposte. Nell'ultima riga permettiamo ad altri utenti (incluso nginx) di essere in grado di leggere e scrivere da quel socket.

Avvia di nuovo uwsgi con uwsgi --ini uwsgi.ini . Ora indirizza nuovamente il browser a localhost e vedrai di nuovo il saluto "Hello uWSGI".

Si noti che è ancora possibile vedere la risposta su localhost:5000 perché uWSGI ora serve l'applicazione tramite http e il socket. Quindi disabilitiamo l'opzione http nel file ini

http = :5000  # <-- remove this line and restart uwsgi

Ora è possibile accedere all'app solo da nginx (o leggendo direttamente da tale socket :)).

Abilita lo streaming dal pallone

Flask ha quella caratteristica che ti permette di trasmettere i dati da una vista usando i generatori.

Cambiamo il file app.py

  • aggiungere from flask import Response
  • aggiungi from datetime import datetime
  • aggiungere from time import sleep
  • crea una nuova vista:
@app.route("/time/")
def time():
    def streamer():
        while True:
            yield "<p>{}</p>".format(datetime.now())
            sleep(1)

    return Response(streamer())

Ora apri il tuo browser su localhost/time/ . Il sito verrà caricato per sempre perché nginx attende fino al completamento della risposta. In questo caso la risposta non sarà mai completa perché invierà per sempre la data e l'ora correnti.

Per evitare l'attesa di nginx, è necessario aggiungere una nuova riga alla configurazione.

Modifica /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 linea uwsgi_buffering off; dice a nginx di non aspettare fino al completamento di una risposta.

Riavvia nginx: il sudo service nginx restart e guarda localhost/time/ again.

Ora vedrai che ogni secondo appare una nuova linea.

Configurazione di Flask Application, uWGSI, Nginx - Modello di configurazione delle configurazioni del server (predefinito, proxy e cache)

Questo è un porting di setup originato dal tutorial di DigitalOcean su How to Serve Flask Applications con uWSGI e Nginx su Ubuntu 14.04

e alcune utili risorse git per i server nginx.

Applicazione del matraccio

Questo tutorial presume che tu usi Ubuntu.

  1. locate var/www/ folder.
  2. Crea la tua cartella web app mkdir myexample
  3. cd myexample

facoltativo Si consiglia di configurare l'ambiente virtuale per la distribuzione di applicazioni Web sul server di produzione.

sudo pip install virtualenv

per installare l'ambiente virtuale.

virtualenv myexample

per configurare l'ambiente virtuale per la tua app.

source myprojectenv/bin/activate 

per attivare il tuo ambiente. Qui installerai tutti i pacchetti python.

fine opzionale ma raccomandato

Configura flask e gateway uWSGI

Installa il pallone e il gateway uSWGI:

pip install uwsgi flask

Esempio di app per flask in 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')

Crea un file per comunicare tra la tua app Web e il server web: interfaccia gateway [ https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface]

nano wsgi.py

quindi importa il modulo webapp e fallo partire dal punto di ingresso del gateway.

from myexample import application

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

Per testare uWSGI:

uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi

Per configurare uWSGI:

  1. Creare un file di configurazione .ini

    nano myexample.ini

  2. Configurazione di base per 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

facoltativo se si utilizza l'ambiente virtuale È possibile deactivate l'ambiente virtuale.

Configurazione di Nginx Useremo nginx come:

  1. server predefinito per passare la richiesta al socket, usando il protocollo uwsgi
  2. server proxy davanti al server predefinito
  3. cache server per memorizzare le richieste riuscite (ad esempio, potresti voler memorizzare nella cache richieste GET se la tua applicazione web)

Individua la directory dei sites-available e crea un file di configurazione per la tua applicazione:

sudo nano /etc/nginx/sites-available/myexample

Aggiungi il seguente blocco, nei commenti cosa fa:

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;
    }
}

Infine, collega il file alla directory sites-enabled ai sites-enabled . Per una spiegazione dei siti disponibili e abilitati, vedi risposta: [ http://serverfault.com/a/527644]

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

Hai finito ora con nginx. Tuttavia, potresti voler controllare questo modello di caldaia molto prezioso: [ https://github.com/h5bp/server-configs-nginx]

Molto utile per la messa a punto.

Ora prova Nginx:

sudo nginx -t

Avvia Nginx:

sudo service nginx restart

Automatizzare Ubuntu per avviare uWSGI L'ultima cosa è fare in modo che Ubuntu avvii il gateway wsgi comunicando con l'applicazione, altrimenti dovresti farlo manualmente.

  1. Individua la directory per gli script di inizializzazione in Ubuntu e crea un nuovo script:

sudo nano /etc/init/myexample.conf

  1. Aggiungi blocco successivo, commenti in linea per spiegare cosa fa

    # 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
    
    

Ora puoi attivare il tuo script: sudo start myexample



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow