Share
Embed
Transcript
17 slides
-
Développement web asynchrone avec Tornado Ronan Amicel @amicel PyCon FR
– Paris – 15 septembre 2012 -
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 -
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() -
(Some) Batteries Included • Moteur de templates • Localisation •
Client HTTP asynchrone • Client MySQL asynchrone • OpenID et OAuth (Twitter, Facebook, Google) • Web Socket -
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 -
Mises à jour « temps réel » Polling (Ajax) Long
Polling (Comet) Streaming (Web Socket) Navigateur Serveur Navigateur Serveur Navigateur Serveur événements événements événements -
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" -
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); }; -
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() -
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() -
Tâches concurrentes avec tornado.gen class MyRequestHandler(RequestHandler): @asynchronous @engine def get(self):
http = AsyncHTTPClient() response1, response2 = yield [ Task(http.fetch, url1), Task(http.fetch, url2), ] self.write('Downloaded!') self.finish() -
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 -
Les côtés négatifs • Asynchrone – Moins lisible que du
code synchrone – Plus complexe à déboguer • Communauté – Moins populaire que Django, Flask, Pyramid...