gunicorn 默认只启1个worker进程,无法利用多核CPU;应显式设-w参数(如-w 4),并开启--preload避免重复初始化;禁用--threads以防线程不安全;gevent需monkey.patch_all()且适用于IO密集型场景,CPU密集型仍用多进程更稳。

gunicorn 启动 Django 时为什么没用上多核
默认 gunicorn 只开 1 个 worker,哪怕你机器有 8 核,也只压着一个 CPU 跑。Django 本身是同步阻塞的,不靠多进程(或协程)根本没法吃满 CPU。
实操建议:
- 显式指定
-w参数,比如-w 4开 4 个 worker 进程(一般设为 CPU 核数 × 2,但别盲目堆高——每个 worker 都吃内存) - 确认
--preload是否开启:不开的话,每个 worker 会单独导入 Django,可能触发重复初始化、DB 连接泄漏;开了则主进程先加载再 fork,更安全 - 避免用
--threads混合多线程:Django 的 ORM 和中间件大多非线程安全,线程数 >1 容易出DatabaseError: database is locked或状态错乱
gevent 协程真能提升并发?什么场景下反而拖后腿
gevent 把阻塞调用(如 HTTP 请求、DB 查询、文件读写)自动转成协程让出控制权,单个 worker 就能并发处理几百连接——但前提是这些 IO 真的被 gevent patch 住了。
实操建议:
- 必须在最开头(
manage.py或gunicorn.conf.py顶部)加from gevent import monkey; monkey.patch_all(),漏掉patch_ssl=True会导致 HTTPS 请求卡死 - Django 的
runserver不支持 gevent,必须用gunicorn --worker-class=gevent --workers=2 --worker-connections=1000启动 - 如果代码里有大量 CPU 密集操作(比如 Pandas 计算、图像处理),gevent 无济于事,反而因协程调度增加开销;这时老老实实用多进程 +
-w更稳
worker 类型选 sync / gevent / eventlet?看日志和错误再决定
不是越“高级”的 worker 类型越好。sync 最简单可靠,gevent 性能高但依赖 patch,eventlet 类似但社区维护弱、Python 3.11+ 兼容性差。
常见错误现象:
-
ImportError: No module named 'gevent.monkey'→ 忘装gevent或没 import monkey -
BlockingIOError: [Errno 11] Resource temporarily unavailable→worker-connections设太高,超出系统文件描述符限制(用ulimit -n查,需同步调大) - HTTP 请求超时、部分请求直接 502 → gevent 下 DB 连接池没配好,
CONN_MAX_AGE=0是必须的,否则连接在协程间复用出错
配置里最容易被忽略的三个硬指标
并发能力不只看 worker 数,这三个参数不调,再多进程也白搭。
-
--timeout 30:默认 30 秒,长耗时接口(如导出)会直接被 kill,按业务设高,但别设成 0(禁用超时) -
--keep-alive 5:HTTP Keep-Alive 保持时间,太短导致频繁建连,太长占着 worker 不放人,5–10 秒较平衡 -
--max-requests 1000:强制 worker 重启,防内存泄漏(尤其用了 C 扩展或全局缓存时),不设可能跑几天后 OOM
真实线上环境里,--worker-class=gevent 和 --max-requests 组合用得最多——协程省资源,定期重启兜底。










