Asyncio in production
Hrafn Eiriksson
Why you no asyncio?!
Why you no asyncio?!
Asynchronous programming is different
Why you no asyncio?!
asyncio is relatively new
Why you no asyncio?!
Converting existing Python apps to use asyncio is not simple
Why you no asyncio?!
The community has built multiple concurrency libraries
Why you no asyncio?!
Asynchronous programming is not always what you want
My goal today
1. Discuss why I went all in on asyncio (and try to convince you to do the same)
2. Migrating to asyncio and the inevitable issues you run into
3. Asyncio in production: A before/after comparison
Not my goal today
4. An introduction into asyncio
Part 1: Why bother with asyncio?
My software already works!
A bit of background...
A bit of background...
Credit: https://www.destroyallsoftware.com/talks/wat
A bit of background...
How we (typically) scale our services
Instance 1
Gunicorn
worker 1
Instance 2
Gunicorn
Clients Gunicorn worker 2
Instance 3
master
Load
Gunicorn
balancer
Instance 4 worker 3
... ...
Gunicorn
Instance x
worker y
flow
TLDR
What makes asyncio so attractive is that it’s:
- Explicit
- Part of the language
Part 2: Migrating to asyncio
The asyncio ecosystem
Previously people relied on monkey patching
Now it seems to be becoming quite mature:
- Dozens of web frameworks (aiohttp, Sanic, Quart)
- Loads of database drivers (asyncpg, aiomysql, aioredis, etc)
- ...and way more [1]
[1] https://github.com/python/asyncio/wiki/ThirdParty
A microservice migration
Based on a true story
Asyncio web frameworks
Sanic
aiohttp
WebSockets
support
Mature
Flask-like
Fast
Flask compatible
HTTP 2.0
An example: Quart
Flask Quart [2]
[2] https://gitlab.com/pgjones/quart
aiohttp
A migration example: Sentry
Then problems hit...
Issues with asyncio
- A lot of new concepts to wrap your head around
- async/await everywhere
- Debugging asyncio code can be problematic
- Be wary of running synchronous code in async functions
TLDR
1. Map out your dependencies to see if asyncio-compatible versions exist
2. Experiment with asyncio versions of your dependencies
3. Watch out for asyncio gotchas
4. Profit!
Part 3: asyncio in production
Before/after comparison
Before: Flask + psycopg2 + eventlet
VS
After: aiohttp + asyncpg + uvloop
Methodology
- Use wrk (https://github.com/wg/wrk) to do HTTP benchmarking.
- Ran each configuration of the benchmark:
- For 30 seconds
- 10 times
- Using a variable number of open HTTP connections
- Noted the median and the 25%/75% latency for each run
- 10 seconds of sleep between runs
Local comparison: Simple ping
Requests/sec
Local comparison: Database access
Requests/sec
In production comparison
Requests/sec
Conclusion
So is asyncio worth the effort?
Thank you!