Il web è un posto grande ora. Abbiamo bisogno di supportare migliaia di clienti alla volta, ed ecco che arriva Tornado. Tornado è un framework web Python e una libreria di rete asincrona, originariamente sviluppata da FriendFreed.
Tornado usa network-io non bloccante. Grazie a questo, può gestire migliaia di connessioni server attive. È un salvatore per le applicazioni in cui vengono mantenuti lunghi sondaggi e un gran numero di connessioni attive.
Tornado non è come la maggior parte dei framework Python. Non è basato su WSGI, anche se supporta alcune caratteristiche di WSGI usando il modulo `tornado.wsgi`. Utilizza un design a ciclo di eventi che rende l’esecuzione delle richieste di Tornado più veloce.
Che cos’è il programma sincrono?
Una funzione si blocca, esegue il suo calcolo e ritorna, una volta fatto. Una funzione può bloccarsi per molte ragioni: I/O di rete, I/O su disco, mutex, ecc.
Le prestazioni dell’applicazione dipendono da quanto efficientemente l’applicazione usa i cicli della CPU, ecco perché le dichiarazioni/chiamate bloccanti devono essere prese seriamente. Considerate le funzioni di hashing delle password come bcrypt, che per progettazione utilizzano centinaia di millisecondi di tempo della CPU, molto più di un tipico accesso alla rete o al disco. Poiché la CPU non è inattiva, non c’è bisogno di ricorrere a funzioni asincrone.
Una funzione può essere bloccante in una, e non bloccante in altre. Nel contesto di Tornado, consideriamo generalmente il blocco dovuto all’I/O di rete e al disco, anche se tutti i tipi di blocco devono essere ridotti al minimo.
Che cos’è il programma asincrono?
1) Architettura single-threaded:
Significa che non può fare compiti incentrati sul calcolo in parallelo.
2) Concurrency I/O:
Può passare i compiti IO al sistema operativo e continuare al compito successivo per ottenere il parallelismo.
3) epoll/ kqueue:
Sottolinea il costrutto relativo al sistema che permette ad un’applicazione di ottenere eventi su un descrittore di file o compiti specifici di I/O.
4) Ciclo di eventi:
Usa epoll o kqueue per controllare se è successo qualche evento, ed esegue callback che è in attesa di quegli eventi di rete.
Asynchronous vs Synchronous Web Framework:
Nel caso del modello sincrono, ogni richiesta o compito viene trasferito al thread o al routing, e come finisce, il risultato viene consegnato al chiamante. Qui, la gestione delle cose è facile, ma la creazione di nuovi thread è troppo overhead.
D’altra parte, nel framework asincrono, come Node.js, c’è un modello single-threaded, quindi molto meno overhead, ma ha complessità.
Immaginiamo migliaia di richieste in arrivo e un server usa cicli di eventi e callback. Ora, finché la richiesta non viene elaborata, deve memorizzare e gestire in modo efficiente lo stato di quella richiesta per mappare il risultato del callback al client attuale.
Node.js vs Tornado
La maggior parte di questi punti di confronto sono legati al linguaggio di programmazione attuale e non al framework:
- Node.js ha un grande vantaggio che tutte le sue librerie sono Async. In Python, ci sono molti pacchetti disponibili, ma pochissimi di essi sono asincroni
- Come Node.js è JavaScript runtime, e possiamo usare JS sia per il front-end che per il back-end, gli sviluppatori possono mantenere solo una codebase e condividere la stessa libreria di utilità
- Il motore V8 di Google rende Node.js più veloce di Tornado. Ma molte librerie Python sono scritte in C e possono essere alternative più veloci.
Un semplice esempio di ‘Hello World’
CODE: https://gist.github.com/velotiotech/b4d91554b739f2487bf6131ac65ec06d.js
Nota: Questo esempio non usa nessuna funzione asincrona.
Utilizzando il modulo AsyncHTTPClient, possiamo fare chiamate REST asincrone.
CODE: https://gist.github.com/velotiotech/5fe63eb5fd6cf3af9bf353c2fd3b4ca7.js
Come potete vedere `yield http_client.fetch(url)` verrà eseguito come una coroutine.
Esempio complesso di Tornado Async
Per favore date un’occhiata al gestore della richiesta asincrona.
WebSockets utilizzando Tornado:
Tornado ha un pacchetto integrato per WebSockets che può essere facilmente utilizzato con le coroutine per ottenere la concorrenza, ecco un esempio:
CODE: https://gist.github.com/velotiotech/34d0a0e0ecd57818ae1db1697c075777.js
Si può usare un’applicazione client WebSocket per connettersi al server, il messaggio può essere qualsiasi intero. Dopo l’elaborazione, il client riceve il risultato se l’intero è primo o no.
Ecco un altro esempio delle effettive caratteristiche asincrone di Tornado. Molti lo troveranno simile alle goroutine e ai canali di Golang.
In questo esempio, possiamo avviare uno o più worker e questi ascolteranno la ‘tornado.queue’. Questa coda è asincrona e molto simile al pacchetto asyncio.
CODE: https://gist.github.com/velotiotech/1477131948ca23879167df0281726d02.js
Conclusione
1) I framework asincroni non sono molto utili quando la maggior parte dei calcoli sono incentrati sulla CPU e non sull’I/O.
2) A causa di un singolo thread per modello core e del ciclo di eventi, può gestire migliaia di connessioni client attive.
3) Molti dicono che Django è troppo grande, Flask è troppo piccolo, e Tornado è giusto:)