Uvicorn默认用C实现的httptools(解析快、调试难),Hypercorn默认用纯Python的h11(可调试、RPS低15%~20%);生产用--http httptools,调试WebSocket可临时切h11;Hypercorn需--h2显式启用HTTP/2。

Uvicorn 和 Hypercorn 的 --http 参数差异直接影响 HTTP 解析性能
httptools 和 h11 是两个主流的 HTTP 解析后端,uvicorn 默认用 httptools(C 实现),hypercorn 默认用 h11(纯 Python)。前者解析更快但调试困难,后者可直接打断点、兼容性好,但压测下 RPS 通常低 15%~20%。如果你在开发中频繁遇到 InvalidHTTPVersion 或 UnexpectedFrameType 类错误,先检查是否混用了 --http h11 和 WebSocket 升级逻辑——h11 对 Upgrade 头的容错不如 httptools 严格。
实操建议:
- 生产环境固定用
--http httptools,不要省略; - 本地调试 WebSocket 时可临时切
--http h11,方便查scope字段是否缺失subprotocols; -
hypercorn若想提性能,得显式加--h2启用 HTTP/2 支持,否则默认仍走 HTTP/1.1 路径。
worker 数量不是越多越好,Uvicorn 的 uvloop 和 CPU 核心数强绑定
uvicorn 每个 worker 绑定一个独立事件循环,而 uvloop 本质是单线程的 libuv 封装。这意味着:4 核机器设 --workers 8 不仅不提升吞吐,还会因进程调度开销导致延迟抖动上升。我们在线上实测过,当 --workers 超过 os.cpu_count() + 1 后,RPS 反而下降 7%~12%,timeout-keep-alive 超时率也明显升高。
对比 hypercorn:它支持 --worker-class trio 或 --worker-class asyncio,其中 trio 可在单 worker 内跑多个任务流,对 IO 密集型长连接更友好。但代价是内存占用高 20%,且不兼容部分依赖 asyncio.get_event_loop() 的旧库。
容易踩的坑:
- 别在 Docker 容器里用
os.cpu_count()算 worker 数——cgroups 限制下它可能返回宿主机核数; -
uvicorn的--workers和gunicorn的--workers行为完全不同,前者是多进程+多事件循环,后者是多进程+多线程; - 若应用里有阻塞调用(如
time.sleep(1)或未异步化的数据库驱动),再多 worker 也救不了,必须改用run_in_executor。
Daphne 在 WebSocket 场景下比 Uvicorn 更稳,但 HTTP 吞吐低近一半
daphne 是 Django Channels 官方服务器,底层用 twisted,对 WebSocket 连接生命周期管理更细粒度。比如客户端断连时,daphne 能更早触发 websocket.disconnect 事件,而 uvicorn 有时要等 keep-alive 超时才清理连接,导致内存里堆积大量 STATE_DISCONNECTED 的协程对象。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
不过它的 HTTP 性能短板明显:同样 4 核机器、100 并发压测,daphne 的 RPS 稳定在 4800 左右,uvicorn 能到 9200+。这不是配置问题,而是 twisted 的 reactor 模型在短连接场景下调度开销更大。
适用判断:
- 纯 WebSocket 服务(如聊天室后端)→ 优先
daphne; - 混合 HTTP + WebSocket(如 FastAPI 接口带实时通知)→
uvicorn更均衡,但得手动在receive循环里加if event['type'] == 'websocket.disconnect'清理资源; - 若用
daphne部署 FastAPI,注意它不支持lifespan协议,startup/shutdown事件不会触发。
Granian 是唯一绕过 GIL 的 ASGI 服务器,但生态兼容性最差
granian 用 Rust 写核心网络层,Python 层只做协议桥接,因此单 worker 就能压满多核。实测 4 核机器跑 granian main:app --workers 1,RPS 达到 59k,是 uvicorn 的 2.7 倍。但它不兼容任何基于 asyncio 的中间件(比如 slowapi 限流器),所有依赖 asyncio.create_task 的代码都会报 RuntimeError: no running event loop。
目前它只认 ASGI 3.0 签名,不支持 scope 里传 asgi 字段的老版本应用。如果你的项目用了 starlette 0.22 以下或 fastapi 0.95 以下,启动直接失败。
真实约束:
- 不能用
logging的异步 handler(会卡死); -
sqlite3必须配check_same_thread=False,否则多线程写入报错; - 调试时没法用
pdb断点进请求处理函数——Rust 层把 Python 调用栈截断了。
scope 生命周期和服务器超时参数的错位。比如 uvicorn 的 --timeout-keep-alive 5 和应用里 await receive() 的等待时间没对齐,就可能让连接在服务器层已关闭,但应用还在等下一个事件,最终卡住整个 worker。这种问题不会报错,只会表现为“偶发性响应延迟突增”,得靠 strace -p $(pgrep uvicorn) 看系统调用才能定位。


















