uWSGI e' un application server container scritto in c che permette il deploy di applicazioni di vario tipo, fornendo loro un ambiente solido e ricco di funzionalita' (nonche' estremamente performante). E' completamente opensource, quindi il modo migliore di apprenderlo e' utilizzarlo in locale (solo se avete un sistema POSIX-compliant, incluso MacOSX)
applicazione WSGI:
Un'applicazione wsgi deve rispettare pochi e semplici requisiti, un semplice esempio potrebbe essere il seguente (salvatelo all'interno del file hello.py):
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
yield 'Hello World\n'Vogliamo farla girare nel nostro account Unbit (per cui ovviamente avremo gia' creato la docroot dentro /www, se ad esempio il dominio e' pippo.it la docroot sara' /www/pippo.it).
Copiamo il file hello.py nella docroot e decidiamo quale versione di python vogliamo usare.
Poniamo che sia python 2.6.6
Andiamo sul pannello e nelle opzioni del dominio spuntiamo il flag upstream e nel campo upstream_cmd inseriamo il comando da lanciare:
uwsgi --plugins python266 hello.py
Attendiamo i soliti 30 secondi e visitiamo il nostro sito che restituira' il classico Hello World.
Se invece avessimo voluto utilizzare python 2.7.2 il comando sarebbe stato
uwsgi --plugins python272 hello.py
applicazione Rack:
Sinatra e' sicuramente uno dei microframework che ha avuto maggiore successo nel mondo ruby:
require 'rubygems' require 'sinatra' get '/hi' do "Hello World!" end run Sinatra::Application
salviamo il file nella docroot (chiamatelo hello.ru) e in upstream_cmd impostate
uwsgi --plugins rack187 hello.ru
Ogni processo uWSGI puo' gestire piu' applicazioni montate sotto uri differenti.
Vogliamo montare la nostra applicazione hello sotto /saluta e (crepi l'avarizia) anche sotto /ciao, mentre tutte le altre richieste saranno mappate sul webserver come se uWSGI non fosse attivo.
La configurazione di uWSGI iniziera' a diventare un po' "massiccia", quindi usare la command line e' poco pratico. Ci serviremo di un file di configurazione (chiamatelo pippo.ini).
[uwsgi] plugins = python270 mount = /ciao=hello.py mount = /saluta=hello.py manage-script-name = true
Ora (dopo aver copiato pippo.ini nella docroot) modifichiamo upstream_cmd in
uwsgi pippo.ini
A questo punto sara' necessario riavviare la vecchia istanza di uWSGI in esecuzione (quella che abbiamo avviato per hello.py). Andiamo sul pannello, nella gestione processi, e inviamo il segnale di KILL.
Ora visitiamo /ciao e /saluta e l'applicazione dovrebbe rispondere.
Noteremo pero' che il dominio risponde anche ad alte url, questo perche' non abbiamo detto al webserver quali punti di montaggio ci interessano, e lui, nel dubbio, passa tutto ad uWSGI.
Editiamo il campo upstream_only elencando i punti di montaggio che vogliamo siano gestiti da uWSGI:
/ciao /saluta
Attendiamo 30 secondi e il gioco e' fatto.
Esistono 2 timeout rilevanti in uWSGI. Il primo (gestito da upstream_timeout) e' il tempo massimo che il webserver puo' attendere la risposta ad una richiesta fatta a uWSGI. Scaduto il timeout il webserver restituisce un errore.
Ovviamente l'errore non implica che la richiesta che sta gestendo uWSGI sia interrotta, ma solo che il webserver per motivi di sicurezza non puo' tenere occupato uno slot in attesa di una risposta che potrebbe non arrivare mai.
Per bloccare invece una richiesta direttamente all'interno di uWSGI, l'unico modo e' che quest'ultimo si autotermini (TM)
Questa feature di uWSGI, si chiama harakiri
Per impostarlo si usa l'opzione --harakiri <n>, dove <n> e' il numero massimo di secondi che una richiesta puo' impiegare.
La modalita' harakiri si comporta diversamente in base alla presenza (o meno) del cosiddetto processo master.
Il processo master e' uno dei componenti fondamentali dello stack uWSGI. Permette una gestione affidabile dell'harakiri, un monitoraggio costante dei processi che compongono lo stack, ed e' la base per il signal framework (fare riferimento alla doc ufficiale). Se avete un processo Unbit (o memoria disponibile nel vostro container) da dedicargli abilitatelo sempre con --master.
Di base uWSGI puo' eseguire una sola richiesta alla volta (mono-processo). Questo puo' bastare per molte applicazioni, ma se non e' sufficiente, potete usare una delle varie modalita' supportate da uWSGI:
multiprocesso: vengono lanciate N copie del processo (opzione --processes <n>)
multithread: vengono lanciati N threads per processo (opzione --threads <n>)
async: se la propria applicazione e' non bloccante si possono generare N async core (opzione --async <n>)
async+ugreen: implementazione nativa di green threads in uWSGI ( --async <n> --ugreen)
async+greenlet: utilizzo di greenlet ( --async <n> --greenlet, richiede il plugin greenlet)
async+stackless: utilizza le tasklets di stackless python (--async <n> --stackless, richiede il plugin stackless)
async+gevent: utilizza gevent come loop engine (--async <n> --loop gevent, richiede il plugin gevent)
async+fiber: utilizza le fiber di ruby 1.9 (--async <n> --loop fiber, richiede il plugin fiber)
uWSGI supporta la syscall sendfile(), per i piu' tecnici si tratta di un modo efficiente di inviare un flusso di dati da un file descriptor a un socket senza disturbare lo userspace.
Sebbene sia molto efficiente e' preferibile far servire (ove possibile) i file statici direttamente al webserver. Questo evita di dover passare la richiesta a uWSGI e tenerlo impegnato in operazioni che puo' fare qualcun altro.
Il parametro upstream_off permette di elencare le url per cui si vuole che il controllo non sia passato a uWSGI (e' l'esatto opposto di upstream_only visto poco prima). Ad esempio in ambiente Django e' opportuno elencare in upstream_off /media
Sebbene python non sia certo un divoratore di memoria come invece lo sono alcuni suoi cugini, e' buona norma prima di andare in produzione, verificare il consumo di address space e rss della propria applicazione sotto carico.
L'opzione --memory-report aggiunge al file di log di uWSGI (vedi prossima sezione) il quantitativo di address space e rss occupati dopo ogni richiesta. Questa funzionalita' introduce un piccolo overhead, quindi se siete dei maniaci dei microsecondi disabilitatela una volta in produzione.
uWSGI non sarebbe un buon server senza un sistema di logging adeguato. Per ogni richiesta vengono riportate la data, l'ip del richiedente, il numero di variabili passate dal webserver, il tempo impiegato a processare la singola richiesta (in millisecondi), stato http, protocollo http,bytes restituiti e qualche altra cosina utile.
Di default ogni processo uWSGI logga nello stderr_log. Tramite l'opzione --logto e' possibile specificare un file alternativo per ogni dominio/istanza
Alcune applicazioni potrebbero dover generare dei threads. Se uWSGI non viene avviato in modalita' multithread, il supporto per i threads e' disabilitato. Se volete permettere alle vostre applicazioni di generare threads ma senza trasformare uWSGI in un server multi-threaded, usate l'opzione --enable-threads
Questa pagina vuole essere solo una piccola introduzione, se volete approfondire questo prodotto, il modo migliore e' consultare il sito ufficiale:
http://projects.unbit.it/uwsgi/wiki
ed in particolare le sezioni:
http://projects.unbit.it/uwsgi/wiki/Quickstart http://projects.unbit.it/uwsgi/wiki/Example http://projects.unbit.it/uwsgi/wiki/Doc
In alterantiva potete iscrivervi alla mailing-list ufficiale:
http://lists.unbit.it/cgi-bin/mailman/listinfo/uwsgi
O entrare nel canale irc #uwsgi su freenode
uWSGI (l'ultima modifica รจ del 2011-09-09 16:04:50, fatta da RobertoDeIoris)