Asynchronous web development
with Python
Anton Caceres
Stefan Behnel
About Us
Anton Caceres, Stefan Behnel –
Software Developers at Skoobe GmbH
Skoobe:
• eBook subscription service
• 45 000+ books
• new titles weekly
• Android and iOS
Every day,
almost 2 years of reading
Outline
• Web servers - threading vs. async
• Asynchronous programming basics
• Code session with Python/Tornado
Frontend and Backend
Many page resources, Ajax, WebSockets, …
!
More and more backend requests per client -
Are web-servers ready for it?
Options to solve the problem:
• Scale hardware
• Run efficient software
Threaded web server
HTTPServer
T
T
T
T
...
...
Client-Requests
The naïve approach:
every request in a new thread
Threaded web server
# requests
#responses
The naïve approach:
every request in a new thread
Threaded web server with pool
The better approach:
every request in a free thread from pool
HTTPServer
T
T
T
...
Client-Requests
}n
Threaded web server with pool
# requests
#responses
The better approach:
every request in a free thread from pool
Threaded web server problem
Common bottleneck:
Threads spend most time waiting for I/O
T
T
T
T
...
I/O
I/O
I/O
I/O
Blocking!
Client-Requests
HTTPServer
Asynchronous Web-ServerClient
Requests
...
Processing
Processing
ProcessingProcessing
I/O
Loop
Processing
The non-blocking approach:
Process whenever you can
The non-blocking approach
# requests
#responses
Asynchronous Web-Server
Asynchronous Web Server
Should be efficient not only for server,
but also for developers
!
Nice if your language provides:
● Coroutines
● Continuations
!
Not nice if you need to code callback-spaghetti
Nooooo!…
before(function (done) {!
server.server(options, function (s, db, providers) {!
//clear db and add a test user - "testuser"!
db.user.remove({}, function () {!
db.notification.remove({}, function () {!
providers.provider1.insertBulk(item1, item2, item3],!
function (err, result) {!
providers.provider2.insert([item1, item2, item3]!
function (err, result) {!
providers.provider3.insert([item1, item2, item3]!
function (err, result) {!
providers.provider4.insert([item1, item2, item3],!
function (err, result) {!
s.listen();!
done();!
})!
});!
});!
});!
});!
});!
});!
});
Real code from mongojs repository
Tornado Web Framework
● Single-threaded
● Asynchronous
● Scalable
● Simple
● Free (Apache license 2.0)
!
Similar to Node.js, EventMachine, …
Originally created at FriendFeed
Developed by Facebook
Writing asynchronous
code
The practical part
Overview
Simple use-case:
• A web-service that makes 3 requests to
external APIs and returns an aggregated
response to the client.
!
In practical part we will:
• Create a blocking handler with Tornado
• Make this handler asynchronous
• Run some benchmarks to compare Tornado
with other asynchronous frameworks
Blocking handler, Tornado
Making code run async
• Turn handler method into coroutine
• Change HTTPClient to AsyncHTTPClient to
make it return Futures
• Yield Futures back to IOLoop
Async handler, Tornado
More Async frameworks
There is a plenty of options for other
programming languages:
!
• Event Machine for Ruby
• Finagle for Scala
• Node.js
!
Next, same code for Node and Finagle
Async handler, Node.js
Async handler, Finagle
(thanks to Gutefrage.net guys)
Some benchmarks
Which server will handle an increasing
amount of parallel requests better?
!
Lets make a simple benchmark:
Change amount parallel requests from 1 to 20
Measure an average time it takes for different
web servers
Plot results on the graph
Some benchmarks
Some benchmarks
Some benchmarks
• Node.js is fastest in beginning, but slowest in
the end
• Finagle is slowest in beginning, but fastest in
the end
• Tornado is somewhere in the middle
• You could help with more examples?
Contact me!
Thank you!
Questions?
!
!
Anton: anton@caceres.me, Stefan: stb@skoobe.de

Asynchronous web-development with Python