Upload
dima-malenko
View
1.123
Download
0
Embed Size (px)
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