Tornado - different Web programming

Preview:

DESCRIPTION

Slides from talk about Tornado Web framework for Dnipro Ruby community

Citation preview

– different Web programming

Dima Malenko

for Ruby Meetup

2002

C++Win32MFCCORBA

ASP.NET Web Forms

public class FirstPage: System.Web.UI.Page{ public System.Web.UI.WebControls.Label lblMessage;

private int i = 0;

protected void Page_Load(object sender, EventArgs e) { i = i + 1; lblMessage.Text = i.ToString(); }}

Web Programming Model

Client Server

Request with parameters

HTML response

MVCBest forW

eb

How Web Server Works?

• Create socket• Bind socket• Listen on socket

• Accept new connection from a client• Receive data from the client• Process the request somehow• Send response to the client

• Wait for a new connection

How Web Server Works?

• Create socket• Bind socket• Listen on socket

• Accept new connection from a client• Receive data from the client• Process the request somehow• Send response to the client

• Wait for a new connection

Sep

ara

te t

hre

ad

Why the “separate thread”?

How Web Server Works?

• Create socket• Bind socket• Listen on socket

• Accept new connection from a client• Receive data from the client• Process the request somehow• Send response to the client

• Wait for a new connection

Sep

ara

te t

hre

ad

Threads cost

• Memory overhead– Default thread stack size in Linux – 8M

• Context switches cost– It takes ~2-3µs to switch context in

Linux– http://blog.tsunanet.net/2010/11/how-

long-does-it-take-to-make-context.html

C10k problem

http://www.kegel.com/c10k.html

Non-blocking I/O!

What would you put in front of loaded Web site?

Why Nginx?

Ability to handle more than 10,000 simultaneous connections with a low memory footprint (~2.5 MB per 10k inactive HTTP keep-alive connections)

“Wikipedia

How is that possible?

• Non-blocking networking using fastest interface on any given platform– kqueue (FreeBSD 4.1+)– epoll (Linux 2.6+)– rt signals (Linux 2.2.19+)– /dev/poll (Solaris 7 11/99+)– event ports (Solaris 10)– select– poll

• Python web framework and async networking library

• Originally developed for FriendFeed• Ideal for long polling, WebSockets

and long-lived connections

www.tornadoweb.com

import tornado.ioloopimport tornado.web

class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world")

application = tornado.web.Application([ (r"/", MainHandler),])

if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()

Handling Requests

class ProductHandler(tornado.web.RequestHandler): def get(self, product_id): self.write("Information about " + product_id)

@tornado.web.authenticated def post(self, product_id): # store updated product info

application = tornado.web.Application([ (r"/product/([0-9]+)", ProductHandler)])

Templates<html> <head> <title>{{ title }}</title> </head> <body> <ul> {% for item in items %} <li>{{ escape(item) }}</li> {% end %} </ul> </body> </html>

class MainHandler(tornado.web.RequestHandler): def get(self): items = ["Item 1", "Item 2", "Item 3"] self.render("template.html", title="My title", items=items)

And That’s It?

Web SiteShow list of

currently running apps with their

titles

NodeRuns many real-time applications

AppChanges titles

whenever it wants

Web SiteShow list of

currently running apps with their

titles

NodeRuns many real-time applications

AppChanges titles

whenever it wants

How would you make sure user can see updated titles on the web?

Web SiteShow list of

currently running apps with their

titles

NodeRuns many real-time applications

AppChanges titles

whenever it wants

What if…

300-400ms

AppChanges titles whenever it

wants

AppChanges titles

whenever it wants

AppChanges titles

whenever it wants

AppChanges titles

whenever it wants

AppChanges titles

whenever it wants

Non-blocking Requests

class AppUpdatesHandler(tornado.web.RequestHandler): @tornado.web.asynchronous def get(self): http = tornado.httpclient.AsyncHTTPClient() request = tornado.httpclient.HTTPRequest( "http://www.frontend.com", method="POST", ...) http.fetch(request, callback=self.on_response) self.finish()

def on_response(self, response): if not response.error: log.debug("Title updated”)

WebSockets

class WebSocket(websocket.WebSocketHandler): def open(self): print "WebSocket opened"

def on_message(self, message): print "Message: " + message

def on_close(self): print "WebSocket closed"

How is it possible?

Cooperative Multitasking

How does it work?

• Event loop– Tornado.ioloop.IOLoop– Level-triggered, uses epoll on Linux and

kqueue on BSD

• Futures– Result of an async operation

Coroutines

class AppUpdatesHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @tornado.gen.coroutine def get(self): http = tornado.httpclient.AsyncHTTPClient() request = tornado.httpclient.HTTPRequest( "http://www.frontend.com", method="POST", ...) self.finish() response = yield http.fetch(request) if not response.error: log.debug("Title updated”)

Conclusions

• Web has changed, so programmers should too

• You want to face C10k problem• There means to solve it• Learn to think asynchronously• Check out www.tornadoweb.org

Questions?

www.dmalenko.orgdmalenko@rollapp.com

@dmalenko

Recommended