Tornado in Depth

100
TORNADO IN DEPTH

description

Tornado is a non-blocking light-weight web server and framework. There's been many introductory talks about it, and it's time to look deeper into it: not just what Tornado does, but how it does it and what can we learn from it when designing our own concurrent systems. In this talk I go over the following topics. I cover them in two parts: first I present how to use a certain feature or approach in our applications; then, I dig into Tornado's source code to see how it really works. - Getting Started: quickly get a simple Tornado application up and running. We'll keep digging into, changing and poking this Application for most of the talk. - An Application Listens: what an Application is, how does Tornado start it and how does it process its requests. - Application and IOLoop: we'll look at how the IOLoop receives the connections from the users and passes them on to the Applications. - Scheduled Tasks: we'll see how to schedule tasks and how the IOLoop will run them. - Generators: we'll learn to use generators to handle the responses of our asynchronous calls, and how they work with the IOLoop. Advanced: - Websockets: how to use them and how they work. - IOStream: how do Tornado's non-blocking sockets work. - Database: how to use non-blocking sockets to connect to databases. - Process: how Tornado works with multiple processes. I presented this talk at Europython 2012 and PyGrunn 2012. Code examples: https://bitbucket.org/grimborg/tornado-in-depth/src/tip/examples/

Transcript of Tornado in Depth

Page 1: Tornado in Depth

TORNADOIN DEPTH

Page 2: Tornado in Depth

thor

Page 3: Tornado in Depth

thunder

Page 4: Tornado in Depth

tro

Page 5: Tornado in Depth

tronar

Page 6: Tornado in Depth

tronada

Page 7: Tornado in Depth

tornar

Page 8: Tornado in Depth

tornada

Page 9: Tornado in Depth

tornada

Page 10: Tornado in Depth

tronada+

tornada

Page 11: Tornado in Depth

TORNADO

Page 12: Tornado in Depth

what is it?

Non-blocking web serverBased on epoll / kqueue

Handles 1000s of connectionsPowers FriendFeed

Page 13: Tornado in Depth
Page 14: Tornado in Depth

why do you even care?

Know what you use

I can't trustwhat I don't know

Learning and sharing: fun!

Page 15: Tornado in Depth

what do you use it for?

We built aScalableDistributedFault tolerantHigh load

...thing

Page 16: Tornado in Depth

[CITATION NEEDED]

Page 18: Tornado in Depth

TORNADO

Page 19: Tornado in Depth

what is it made of?

IOLoopCallbacks, Tasks, Timeouts

TCPServerApplication

RequestHandlerGenerators

Page 20: Tornado in Depth

can I extend it?

Sure!It's easy

How would we makea simple TCPServer?

Page 21: Tornado in Depth

0b_tcpserver.py

show me the source!

Page 22: Tornado in Depth

GETTING

STARTED

Page 23: Tornado in Depth

how do I make the simplest app?

Define a RequestHand lerImplement get

Define an App l icat ionTell the application to l i sten

Start the IOLoop

Page 24: Tornado in Depth

01_getting_started.py

show me the source!

Page 25: Tornado in Depth

what is an Application?

Collection of RequestHand lersImplements l i sten :

Starts an HTTPServerSets the Application as request ca l lback

Implements __ca l l__ :Handles the user requests

Page 26: Tornado in Depth

t1_application_listen.py

show me the source!

Page 27: Tornado in Depth

what does Application.__call__ do?

Parses the URLDecides which hand ler to use

and creates an instance of it(each connection gets one)

_executes it(passing any defined transforms to it –e.g, Gzip compression)

Page 28: Tornado in Depth

t2_application_call.py

show me the source!

Page 29: Tornado in Depth

what does RequestHandler._execute do?

Calls the handler methodChecks XSRF cookie

Maybe closes the connection

Page 30: Tornado in Depth

t3_request_handler__execute.py

show me the source!

Page 31: Tornado in Depth

IOLOOP

CALLBACK

TIMEOUT

event

Page 32: Tornado in Depth

Core of TornadoUsable standalone or with WSGI

Used for server and clientSingle instance per process

Small!

what is the IOLoop?

Page 33: Tornado in Depth

Loops foreverExecutes:

Callbacks (asap)Timeouts (when due)Events (when occoured)

what does the IOLoop do?

Page 34: Tornado in Depth

what is an Event?

Something that happened on a socket (fd)

(e.g. a user opened a conneciton)

Appl icat ions define hand lers for Events

Page 35: Tornado in Depth

how do I wait for an Event?

add_hand ler (fd, handler, events)

update_hand ler (fd, handler, events)

remove_hand ler (fd, handler)

“Notify me when I can READ or WR ITE ,

or when there is an ERROR”

Page 36: Tornado in Depth

IOLOOP

THE LOOPin four steps

Page 37: Tornado in Depth

Process CallbacksThey were scheduled by previous:

CallbacksEvent handlers

first process the Callbacks

Page 38: Tornado in Depth

For each Timeout:Is it due now?Run its callback

Calculate the time till next Timeout

second process the Timeouts

Page 39: Tornado in Depth

Poll timeout:Callbacks? Then 0Timeouts? Then time until the next TimeoutNeither? 1 hour

Here the IOLoop blocks

third poll for Events

Page 40: Tornado in Depth

For each (file descriptor, Event):Call its handler

...and repeat the loop

and fourth process the Events

Page 41: Tornado in Depth

THE

EXAMPLE

WHAT it

really does

Page 42: Tornado in Depth

01_getting_started.py

show me the source!

Page 43: Tornado in Depth

Application.listenstarts HTTPServer

calls IOLoop.add_accept_handler(Application.__call__ will handle the ACCEPT event)

and when a client connects...

what does the example do?

Page 44: Tornado in Depth

what does the example do?IOLoop

pollsconnection TCPServer

callsHTTPServer

which is

HTTPConnection

creates

read and callsheaders

body

reads

using callbacks

request_callback

and calls

Application.__call__which is RequestHandler

._executecalls

(after parsing URL)

RequestHandler

calls

get or post or ...calls

HTTPConnectionwrites to

(in chunks)

_auto_finish?finishes

yes

Page 45: Tornado in Depth

t4_simple_ioloop.py

show me the source!

Page 46: Tornado in Depth

Scheduled

tasks

Page 47: Tornado in Depth

how do we schedule a task?

Call me back asapIoloop.add_ca l lback

Call me back laterIoloop.add_t imeout

Call me of tenPer iod icCa l lback

Page 48: Tornado in Depth

02_scheduled_tasks.py

show me the source!

Page 49: Tornado in Depth

how does add_callback work?

Adds the callback to the list of callbacks.

(and wraps it in a threadlocal-like stack context)

Page 50: Tornado in Depth

what do you mean, threadlocal-like?

StackContext

Keeps track of the socket connection

Handles association between socket and Application classes

Page 51: Tornado in Depth

t6_add_callback.py

show me the source!

Page 52: Tornado in Depth

how does add_timeout work?

Pushes the timeout to the heap of timeouts.

(and wraps it in a threadlocal-like stack context too)

Page 53: Tornado in Depth

t7_add_timeout.py

show me the source!

Page 54: Tornado in Depth

how do PeriodicCallbacks work?

star tSchedules the next t imeout to call _runMarks the PeriodicCallback as runn ing

stopRemoves the next t imeoutMarks the PeriodicCallback as stopped

_runCalls the ca l lback(unless stop was called)

Page 55: Tornado in Depth

t8_periodic_callback.py

show me the source!

Page 56: Tornado in Depth

what about Callback?

Indeed.

Page 57: Tornado in Depth

Async

handlers

asynchronous@&

auto_ _finish

Page 58: Tornado in Depth

how does @asynchronous work?

Sets _auto_f in i sh to Fa lse(and does some Exception wrapping)

The connection remains openafter get, post...

Close it yourse l f(whenever you want)

Page 59: Tornado in Depth

03_fetch_async.py

show me the source!

Page 60: Tornado in Depth

I put a callback on your callback

Nested callbacksmake ugly code.

Page 61: Tornado in Depth

what about Callback?

Indeed.

Page 62: Tornado in Depth

generators

Page 63: Tornado in Depth

how do I avoid callbacks?

Use Ca l lback(finally!)

and y ie ld

Or Task

Page 64: Tornado in Depth

04_fetch_gen.py

show me the source!

Page 65: Tornado in Depth

Yield

points

Page 66: Tornado in Depth

what is a YieldPoint?

Something you y ie ld

Then stuf f happens

Page 67: Tornado in Depth

what is a YieldPoint?

Cal lbackSends a resu l t for a key

Wai tWai ts till a resu l t for a key arrives

Wai tManySame as Wai t , for many keys

Page 68: Tornado in Depth

TaskWai t + Ca l lback(with an auto-generated key)

Mul t iList of YeldPoints

what is a YieldPoint?

Page 69: Tornado in Depth

how do we do async processing?

callback=(yield Callback(“key”))

When a result arrives, send it for the key “key”

Let's fetch and return a webpage.

Get

Page 70: Tornado in Depth

how do we do async processing?

response=yield Wait(“key”)

When the result is sent, read it into response.

Let's fetch and return a webpage.

Get

Page 71: Tornado in Depth

04_fetch_gen.py

show me the source!

Page 72: Tornado in Depth

05_task.py

show me the source!

Page 73: Tornado in Depth

t9_yield_points.py

show me the source!

Page 74: Tornado in Depth

websockets

Page 75: Tornado in Depth

how do we use websockets?

Extend WebSocketHand ler(instead of RequestHandler)

Implement on_message Let's fetch and return a webpage.

Get

Page 76: Tornado in Depth

06_websocket.py

show me the source!

Page 77: Tornado in Depth

how do websockets work?

Similar to @asynchronous(the connection is kept open)

After writing, read for more(asynchronously—see IOStream)

To Application, it looks like a RequestHandlerLet's fetch and return a

webpage.Get

Page 78: Tornado in Depth

how does WebSocket work?

_execute

Accepts the connection

Decides the vers ion of the protocol.

Instantiates a WebSocketProtoco l class

Let's fetch and return a webpage.

Get

Page 79: Tornado in Depth

how does WebSocketProtocol work?

accept_connect ionSends the required initial messageReads the next message (asynchronously)

_wr i te_responseWri tes a response on the socketReads the next message (asynchronously)

Let's fetch and return a webpage.

Get

Page 80: Tornado in Depth

ta_websocket.py

show me the source!

Page 81: Tornado in Depth

iostream

Page 82: Tornado in Depth

what does IOStream do?

Communicates with the socket

AsynchronousUses IOLoop Ca l lbacks Let's fetch and return a

webpage.Get

Page 83: Tornado in Depth

how does IOStream work?

_add_ io_state“Notify me when I can READ or WRITE , or when ERROR”schedules Ca l lback for an event (READ, WRITE, ...)

_hand le_eventsCan I read? Call _hand le_readCan I write? Call _hand le_wr i teHandles errors

Let's fetch and return a webpage.

Get

Page 84: Tornado in Depth

how does IOStream work?

_hand le_readStore data in read bufferCall the read callback (_read_from_buffer)

_hand le_wr i teWrite data from the buffer into the socket (handling funny circumstances)

Call the write callback (if it exists)Let's fetch and return a

webpage.Get

Page 85: Tornado in Depth

how does IOStream work?

connectsocket.connect_add_ io_state (WRITE)

readSet callbackData in read buffer? Return itRead buffer empty? _add_ io_state (READ)

wr i teAdd data to write buffer_add_ io_state (WRITE)

Let's fetch and return a webpage.

Get

Page 86: Tornado in Depth

how do I use IOStream directly?

read_unt i l _regexread_unt i l

read_bytesread_unt i l _c lose

All take a callback Let's fetch and return a webpage.

Get

Page 87: Tornado in Depth

how do I use streaming callbacks?

read_bytesread_unt i l _c lose

Param: streaming_ca l lbackData is sent to callback as it arrives

Let's fetch and return a webpage.

Get

Page 88: Tornado in Depth

0a_async_callback.py

show me the source!

Page 89: Tornado in Depth

database

Page 90: Tornado in Depth

how do I talk to a database?

database.connectionquery(“SQL”)

Returns an iterableVery simple Let's fetch and return a

webpage.Get

Page 91: Tornado in Depth

07_db.py

show me the source!

Page 92: Tornado in Depth

Not async!

Page 93: Tornado in Depth

asyncmongo

Page 94: Tornado in Depth

what is asyncmongo?

Asynchronous MongoDB client

Uses Tornado's IOLoopLet's fetch and return a

webpage.Get

Page 95: Tornado in Depth

how do I use asyncmongo?

asyncmongo.Clientdb.f ind

takes a ca l lback parameter Let's fetch and return a webpage.

Get

Page 96: Tornado in Depth

08_mongo.py

show me the source!

Page 97: Tornado in Depth

how does asyncmongo work?

Implements a Connect ionMany: Connect ionPoo lSends data via Tornado's IOStream

Commands send via CursorCursor.send_message

Uses Connection to communicate asynchronously Let's fetch and return a webpage.

Get

Page 98: Tornado in Depth

can we write our own asyncmysql?

DifficultC driver has b lock ing calls

mysql_querymysql_store_resultmysql_use_result

AlternativeUse Twisted's txMySQL with tornado.platform.twistedSlower

Let's fetch and return a webpage.

Get

Page 99: Tornado in Depth

Q A&

Page 100: Tornado in Depth

GRAZIE!

source: uncertain (sorry!)

[email protected]