能,但效果和预期可能不一致;uvicorn默认单进程单线程异步模型,--workers启多进程(各带独立事件循环),--threads仅控制各worker内同步调用的线程池大小,不影响asgi异步请求处理。

uvicorn 启动时 --workers 和 --threads 能一起用吗?
能,但效果和预期可能不一致。uvicorn 默认是单进程 + 单线程的异步模型,加 --workers 会启用多个独立进程(每个进程有自己的事件循环),而 --threads 只在每个 worker 进程内控制线程池大小——它不用于处理 HTTP 请求,只影响同步阻塞调用(比如 time.sleep()、数据库 sync driver、文件读写等)。
-
--workers N:启动 N 个独立 uvicorn 进程,由主进程管理(需--reload关闭,否则 fork 失败) -
--threads M:每个 worker 内部用concurrent.futures.ThreadPoolExecutor(max_workers=M)执行同步函数 - uvicorn 本身不支持多线程处理 ASGI 请求;所有 async route 都跑在主线程的 event loop 上,
--threads对它们没影响
什么时候该开 --workers?又为什么多数情况别乱开
开 --workers 的唯一合理场景是:你确认应用里有大量 CPU 密集型同步代码(如 numpy 计算、图像处理),且无法改造成 async 或用 run_in_executor 显式调度。
- 多进程能绕过 GIL,真正并行利用多核 CPU
- 但代价明显:内存占用翻倍(每个 worker 加载完整 app)、进程间无共享状态、信号处理更复杂、热重载失效(
--reload和--workers互斥) - 如果只是 I/O 密集(HTTP 调用、DB 查询),开多进程反而增加上下文切换开销,不如专注优化 async 实现和连接池
--workers 下的 lifespan 和全局变量行为很危险
uvicorn 的 lifespan 协议(startup/shutdown)会在每个 worker 进程里单独执行一次,不是“整个服务只跑一次”。
-
全局变量(比如
cache = {})在每个 worker 里都是独立副本,互相不可见立即学习“Python免费学习笔记(深入)”;
数据库连接池、Redis 客户端、日志 handler 等如果在模块顶层初始化,会被复制 N 份,可能触发连接数超限或日志重复
网趣购物系统加强升级版下载新版本程序更新主要体现在:完美整合BBS论坛程序,用户只须注册一个帐号,即可全站通用!采用目前流行的Flash滚动切换广告 变换形式多样,受人喜爱!在原有提供的5种在线支付基础上增加北京云网支付!对留言本重新进行编排,加入留言验证码,后台有留言审核开关对购物系统的前台进行了一处安全更新。在原有文字友情链接基础上,增加LOGO友情链接功能强大的6种在线支付方式可选,自由切换。对新闻列表进行了调整,
常见错误现象:
ConnectionRefusedError(Redis 连接池爆满)、psycopg2.OperationalError: too many clients、缓存不一致启动逻辑必须放在
lifespan里,而不是模块顶层所有共享资源(DB、cache、metrics)应通过依赖注入或 lazy init 控制生命周期
不要依赖
atexit或<strong>del</strong>清理,worker 可能被 signal 强杀,不走 Python 正常退出流程
替代方案比硬上多进程更靠谱
真正需要吞吐量时,优先考虑横向扩展(多个 uvicorn 实例 + 反向代理),而不是单机堆 --workers。
- 单机用
--workers 1 --loop auto(默认) +asyncpg/httpx.AsyncClient/aiofiles,90% 场景够用 - CPU 密集任务丢给
run_in_executor,配合--threads控制并发度,避免阻塞 event loop - 必须多进程?用
gunicorn+uvicorn.workers.UvicornWorker,它对 lifespan、信号、reload 支持更稳,配置也更清晰
uvicorn 的多进程不是“开个参数就变快”,它是把单点问题拆成 N 个单点问题——每个点都得自己管好资源、状态、生命周期。稍不注意,就从性能优化变成运维噩梦。









