3. Tornado c’est quoi ?
• Un serveur web
– scalable et non-bloquant (utilise epoll ou kqueue)
• Un framework web
– proche de web.py ou webapp
– exploite l’infrastructure non-bloquante sous-jacente
4. Bonjour les gens !
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Bonjour les gens !")
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
5. (Some) Batteries Included
• Moteur de templates
• Localisation
• Client HTTP asynchrone
• Client MySQL asynchrone
• OpenID et OAuth (Twitter, Facebook, Google)
• Web Socket
6. Cas d'utilisation
• Seul ou en complément d'un framework « classique »
• Sites à forte charge (milliers de requêtes / seconde)
• Messagerie instantanée, chat rooms
• Requêtes dépendant de services externes à latence variable
(API Facebook, Twitter, etc.)
• Mises à jour « temps réel » dans une page web
7. Mises à jour « temps réel »
Polling Long Polling Streaming
(Ajax) (Comet) (Web Socket)
événements
événements
événements
Navigateur Serveur Navigateur Serveur Navigateur Serveur
8. Web Socket
(côté serveur)
from tornado.websocket import WebSocketHandler
class EchoWebSocket(WebSocketHandler):
def open(self):
print "WebSocket opened"
def on_message(self, message):
self.write_message(u"You said: " + message)
def on_close(self):
print "WebSocket closed"
9. Web Socket
(côté client)
var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function () {
ws.send("Hello, world");
};
ws.onmessage = function (evt) {
alert(evt.data);
};
10. Requêtes asynchrones
from tornado.httpclient import AsyncHTTPClient
from tornado.web import RequestHandler, asynchronous
class MyRequestHandler(RequestHandler):
@asynchronous
def get(self):
http = AsyncHTTPClient()
http.fetch('http://friendfeed.com/', self._on_download)
def _on_download(self, response):
self.write('Downloaded!')
self.finish()
11. Masquer les callbacks
avec tornado.gen
from tornado.gen import engine, Task
from tornado.httpclient import AsyncHTTPClient
from tornado.web import RequestHandler, asynchronous
class MyRequestHandler(RequestHandler):
@asynchronous
@engine
def get(self):
http = AsyncHTTPClient()
response = yield Task(http.fetch, 'http://friendfeed.com/')
self.write('Downloaded!')
self.finish()
15. Historique
• 2007 : FriendFeed
• Août 2009 : rachat par Facebook
• Septembre 2009 : première version diffusée sous licence Apache 2.0
• Juillet 2010 : Tornado 1.0
• Juin 2011 : Tornado 2.0
• Septembre 2012 : Tornado 2.4
16. Les côtés négatifs
• Asynchrone
– Moins lisible que du code synchrone
– Plus complexe à déboguer
• Communauté
– Moins populaire que Django, Flask, Pyramid...