Chapter 14 · asyncio Support
Chapter goals: Understand the relationship between Locust's gevent concurrency model and the asyncio ecosystem, master aiolocust usage, and choose the right approach for your scenario.
14.1 Locust's Concurrency Model: gevent
Locust's traditional concurrency is based on gevent — a Python cooperative concurrency library that monkey-patches standard library I/O operations into non-blocking versions. Each virtual User runs in a greenlet (lightweight coroutine):
# Executed automatically when Locust starts
from gevent import monkey
monkey.patch_all() # Replace blocking calls in socket, time, threading, etc.
# Thereafter all User instances run in greenlets; CPU is yielded automatically on I/O waitgevent's advantage: transparent to user code — you write sync code and Locust handles concurrency automatically. Its disadvantage: monkey-patching does not work on C-extension libraries (see Chapter 13).
14.2 aiolocust: Redesign with asyncio
aiolocust is a 2026-born project in the Locust ecosystem that replaces the gevent/requests stack entirely with asyncio/aiohttp, embracing modern Python async standards.
pip install aiolocustBasic usage:
import asyncio
from aiolocust import HttpUser
async def run(user: HttpUser):
async with user.client.get("http://example.com/") as resp:
pass # Handle response
async with user.client.get("http://example.com/") as resp:
# Extra validation beyond just HTTP status:
assert "expected text" in await resp.text()
await asyncio.sleep(0.1)Project status
aiolocust is currently maintained as a standalone project with fewer features than the Locust mainline (more minimalistic), relying on OTEL for visualization. It may merge into Locust or ship with a future major version.
14.3 gevent vs asyncio Comparison
| Dimension | gevent (Locust) | asyncio (aiolocust) |
|---|---|---|
| Concurrency Model | greenlet + monkey-patch | Native async/await |
| Learning Curve | Low (write sync code) | Medium (understand async) |
| C-extension compat | ❌ Cannot patch | ✅ Native support |
| HTTP client | requests | aiohttp |
| WebSocket | Extra library needed | Built into aiohttp |
| Ecosystem | Mature and stable | Rapidly developing |
| Best for | Traditional HTTP API load testing | High concurrency, C-lib deps, WebSocket |
Decision tree
What does your load test need?
├── Only HTTP/HTTPS API → Use Locust (gevent), most mature ecosystem
├── Needs C-extension libs (psycopg2, etc.) → Consider aiolocust
├── Heavy WebSocket long connections → aiolocust or custom extension
├── Team familiar with asyncio → aiolocust feels more natural
└── Need full Web UI and distributed mode → Locust (more features)14.4 Mixing Async Code in Regular Locust
Even without aiolocust, you can call async functions (e.g., asyncpg DB queries) inside Locust tasks:
import asyncio
from locust import User, task, between
class AsyncDbUser(User):
wait_time = between(0.5, 2)
@task
def query_db(self):
# Run async code in a separate event loop
result = asyncio.get_event_loop().run_until_complete(
self.async_query()
)However, this approach defeats the purpose of gevent's concurrent greenlets — each run_until_complete call blocks the greenlet. Use aiolocust instead for true async concurrency.
14.5 Chapter Summary
- Locust's native model is gevent-based: write sync code, get concurrency for free;
- aiolocust offers a modern asyncio/aiohttp stack for C-extension and WebSocket scenarios;
- gevent cannot patch C extensions; asyncio handles them natively;
- Mixing asyncio into gevent Locust blocks greenlets — prefer aiolocust for true async workloads.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. What is gevent's core mechanism for achieving concurrency?
2. When should you choose aiolocust over standard Locust?
3. Why does mixing asyncio.run() inside a gevent greenlet block concurrency?
4. Which HTTP client does aiolocust use under the hood?
🛠️ Hands-On Exercises
- Write a standard Locust test with gevent; measure RPS on 1,000 concurrent users against httpbin.org.
- Install aiolocust; rewrite the same test in async style; compare RPS and code clarity.
- Try using psycopg2 in a standard Locust task; observe the blocking behavior and switch to aiolocust with asyncpg.
Proceed to Chapter 15: Using Locust as a Library.