More than just a pretty web framework: the Tornado IOLoop
-
Upload
gavin-roy -
Category
Technology
-
view
104 -
download
0
description
Transcript of More than just a pretty web framework: the Tornado IOLoop
More than just a pretty web framework:the Tornado IOLoop
Gavin M. Roy
PyCon 2012 Follow me on Twitter: @Crad
According to comScore, myYearbook is one of the 25 most-trafficked sites in the United States as measured by page views, by minutes, and by minutes per visitor per month.
About myYearbook
PyCon 2012 Follow me on Twitter: @Crad
http://www.myyearbook.com/careers
PyCon 2012 Follow me on Twitter: @Crad
Tornado @ myYearbook
• At myYearbook, we used Tornado in high-request-velocity applications.
• Web apps
• Finite State Machine Game Server
• Take what you need? We do.
PyCon 2012 Follow me on Twitter: @Crad
Async Network Programming
• Core revolves around an I/O loop
• Let the Operating System indicate when to read, when to write and when there are errors on sockets.
• select, poll, epoll (Linux), kqueue (BSD)
• Callback-Passing Style
PyCon 2012 Follow me on Twitter: @Crad
Async Network Programming
PyCon 2012 Follow me on Twitter: @Crad
def start(foo): # Do stuff with foo and when done call the next function stuff(callback=next_step, data=foo); def next_step(bar): # Call more_stuff to parse bar more_stuff(callback=last_step, data=bar); def last_step(baz): # Send the response send_response(baz) # Let our handler know we are done finish()
Callback Passing Style
PyCon 2012 Follow me on Twitter: @Crad
tornado.IOLoop
• Core of Tornado’s network stack
• Fast and easy to use
• Single instance per process
• Cross-platform
• Easy to read source: http://goo.gl/VFeAF
• Used for client libraries & server applications
Works on windows but not supported.
C-Based epoll, not required
PyCon 2012 Follow me on Twitter: @Crad
tornado.IOStream
• Convenient utility class for dealing with the IOLoop
• Does most of the work for you
• This too is for use by clients and server applications
PyCon 2012 Follow me on Twitter: @Crad
IOStream: How to read
• read_until_regex(regex, callback)
• read_until(delimiter, callback)
• read_bytes(num_bytes, callback, streaming_callback=None)
• read_until_close(callback, streaming_callback=None)
PyCon 2012 Follow me on Twitter: @Crad
IOStream: What’s Going On?
reading(), writing(), closed()
PyCon 2012 Follow me on Twitter: @Crad
Serious Business Uses
SSL
And that’s why SSLIOStream Exists.
PyCon 2012 Follow me on Twitter: @Crad
tornado.netutil.TCPServer
PyCon 2012 Follow me on Twitter: @Crad
Hello Async Worldfrom tornado import ioloopfrom tornado import netutil
class EchoServer(netutil.TCPServer):
def handle_stream(self, stream, address): self._stream = stream self._read_line()
def _read_line(self): self._stream.read_until('\n', self._handle_read)
def _handle_read(self, data_in): self._stream.write('You sent: %s' % data_in) self._read_line()
if __name__ == '__main__': server = EchoServer() server.listen(2007) ioloop.IOLoop.instance().start() Source: http://goo.gl/eB7z4
PyCon 2012 Follow me on Twitter: @Crad
What just happened?
tornado.stack_context.StackContext
“Slight Magic”
PyCon 2012 Follow me on Twitter: @Crad
Diving Deeper
PyCon 2012 Follow me on Twitter: @Crad
tornado.IOLoop
•IOLoop.instance()
•ioloop.add_handler(fd, handler, events)
•ioloop.update_handler(fd, handler, events)
•ioloop.remove_handler(fd)
PyCon 2012 Follow me on Twitter: @Crad
Events?
READ, WRITE, ERROR
PyCon 2012 Follow me on Twitter: @Crad
“Example”import socketfrom tornado import ioloop
def on_events(fd, events, error=None):
if events & ioloop.IOLoop.READ: print 'Socket read: %r' % fd.recv(1024)
if events & ioloop.IOLoop.ERROR: print 'Error received: %r' % error
if events & ioloop.IOLoop.WRITE: pass
_ioloop = ioloop.IOLoop.instance()fd = socket.socket() # Other stuff needs to be done hereevents_desired = ioloop.IOLoop.READ | ioloop.IOLoop.ERROR _ioloop.add_handler(fd, on_events, events_desired)_ioloop.start()
PyCon 2012 Follow me on Twitter: @Crad
Timers
• add_timeout(deadline, callback)
• remove_timeout(timeout)
add_timeout returns a reference
deadline can be unix timestamp or a datetime.timedelta
PyCon 2012 Follow me on Twitter: @Crad
add_callback(callback)
PyCon 2012 Follow me on Twitter: @Crad
“Pythonic” Simplification
PyCon 2012 Follow me on Twitter: @Crad
tornado.gen
@gen.enginedef foo(): http_client = AsyncHTTPClient() response1, response2 = yield [gen.Task(http_client.fetch, url1), gen.Task(http_client.fetch, url2)]
for coding not in Callback Passing Style:
PyCon 2012 Follow me on Twitter: @Crad
tornado.platform.twisted
PyCon 2012 Follow me on Twitter: @Crad
Last Thoughts
• Single threaded, use processes
• Watch out for resource contention
• Benchmark your application
• Fork work to remote workers
• multiprocessing.reduction
PyCon 2012 Follow me on Twitter: @Crad
# Main processfrom multiprocessing.reduction import reduce_handle
h = reduce_handle(client_socket.fileno())
pipe_to_worker.send(h) #instance of multiprocessing.Pipe
# Worker processfrom multiprocessing.reduction import rebuild_handle
h = pipe.recv()fd = rebuild_handle(h)client_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)client_socket.send("hello from the worker process\r\n")
multiprocessing.reduction:
Questions?