直接用gunicorn app:app在生产环境会出问题,因其默认仅启动1个sync worker,实为单进程运行,无法并发处理请求,导致请求排队、超时及503错误;必须显式配置workers数量、删除app.run()、指定worker-class并验证实际进程数。

为什么直接用 gunicorn app:app 在生产环境会出问题
因为这条命令只启了默认的 1 个 sync worker,等于还是单进程扛压。真实流量一来,请求排队、超时、CPU 利用率却上不去——不是机器不行,是 Gunicorn 没真正“多进程”起来。
常见现象包括:timeout 错误激增、503 Service Unavailable、日志里反复出现 Worker failed to boot 却没报具体异常。
- 必须显式指定
--workers或在配置文件里设workers,不能依赖默认值 - Flask 的
app.run()必须彻底删除或注释掉,否则可能意外触发开发服务器,和 Gunicorn 冲突 - 启动时加
--log-level info,确认输出里真有类似Booting worker with pid: 1234多行(每行一个 worker)
--worker-class 选 sync 还是 uvicorn.workers.UvicornWorker
取决于你的应用类型和框架:
- Flask / Django 等 WSGI 应用:用
sync(默认)最稳妥;若需更高 I/O 并发,可切gevent,但必须在应用入口第一行加from gevent import monkey; monkey.patch_all() - FastAPI / Starlette 等 ASGI 应用:必须用
uvicorn.workers.UvicornWorker,且--workers值要 ≥2,同时确保 Uvicorn 自身不带--workers参数(Gunicorn 已接管进程调度) - 别混用:比如用
uvicorn.workers.UvicornWorker却传--worker-class gevent,会直接启动失败
worker 数量怎么设才不翻车
公式 2 * CPU核心数 + 1 是起点,不是铁律。实际得看负载特征:
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
立即学习“Python免费学习笔记(深入)”;
- CPU 密集型(如图像处理、数值计算):worker 数不宜超过物理核心数,再多反而因进程切换开销拖慢整体
- I/O 密集型(如 API 调用、数据库查询):可设到
2 * CPU核心数 + 1甚至略高,但超过 8 个后 Gunicorn 主进程调度压力明显上升 - 内存敏感场景(如大模型推理服务):每个 worker 都会加载一份应用代码和依赖,worker 越多内存占用线性增长,宁可少配 worker + 加大单 worker 异步并发(如用
UvicornWorker) - 用
ps aux | grep gunicorn看实际进程数,别光信配置文件写的数字
配置文件里最容易被忽略的三个硬性要求
很多服务启动成功但压测打不满 CPU,问题就出在这三处没对齐:
-
bind必须显式指定,且不能和 Nginx 或其他服务端口冲突;生产推荐用 Unix socket(如unix:/tmp/gunicorn.sock),比 TCP 更快更安全 -
preload = True要打开——否则每个 worker 启动时单独导入模块,可能引发初始化竞争(如数据库连接池重复创建、全局缓存错乱) -
timeout和keepalive得配合业务:长耗时接口(如导出报表)要把timeout提到 120+ 秒,否则 worker 被强杀,请求中断无声无息
worker 进程间不共享内存,所有状态(缓存、连接池、全局变量)都得按每个进程独立初始化;这点在调试超时或内存泄漏时最容易被当成“随机故障”忽略。

















