Flask 高并发场景下使用 Gunicorn 配置 worker 数量,通常建议按照 (2 x CPU 核心数) + 1 的经验公式设定,适用于 CPU 密集型任务。风险边界在于过多 worker 会导致内存耗尽和上下文切换开销增加,需根据实际内存容量调整。
先说结论:配置核心是平衡 CPU 利用率与内存消耗,而非单纯追求最大并发数。
- 适合:CPU 密集型 Flask 应用或同步阻塞 IO 场景
- 先准备:确认服务器 CPU 核心数和可用内存上限
- 验收:通过进程监控和负载测试观察请求排队情况
命令速用版
直接启动命令需指定 worker 数量参数 -w,基本格式为 gunicorn -w 核心数计算值 -b 绑定地址 应用入口。
gunicorn -w 4 -b 0.0.0.0:8000 app:app
为什么会这样
Gunicorn 默认使用同步 worker 模型,每个 worker 同一时间只能处理一个请求。
该模型导致如果 worker 数量少于并发请求数,多余请求会进入队列等待。增加 worker 可以利用多核 CPU 并行处理,但每个 worker 都是独立进程,会消耗额外内存。公开资料中没有看到可靠的量化数据表明具体增加多少 worker 能提升多少 QPS,因为这取决于具体业务逻辑耗时。
分步处理
第一步是获取服务器 CPU 核心数,使用命令 nproc 或 lscpu 查看物理核心数量。
第二步是根据公式计算 worker 数量,建议初始值为 (2 x 核心数) + 1,例如 4 核服务器设置为 9 个 worker。
第三步是启动服务并监控内存,使用命令 htop 或 ps aux 观察 gunicorn 进程占用的 Resident Memory 是否接近系统上限。
第四步是根据负载情况微调,如果发现请求排队严重且内存充足,可适当增加 worker 数量。
怎么验证是否生效
验证方法是检查 Gunicorn 日志和进程状态,确认 worker 进程已按预期数量启动且无频繁重启。
查看日志中是否有 "Booting worker with pid" 字样,数量应与配置一致。使用命令 ps aux | grep gunicorn 统计进程数。观察 access 日志中请求响应时间是否稳定,没有出现大量超时。
常见坑
第一个坑是内存溢出,worker 数量过多会导致 OOM Kill,建议设置 max_requests 参数让 worker 定期重启释放内存。
第二个坑是阻塞 IO,如果 Flask 应用包含大量外部 API 调用或数据库等待,同步 worker 会导致并发能力下降,此时业务场景应考虑使用 gevent 等异步 worker 类。
第三个坑是权限问题,不要使用 root 用户运行 Gunicorn,避免安全风险。
常见问题
如何在不重启服务的情况下调整 worker 数量?
Gunicorn 支持发送 HUP 信号重载配置,但修改 worker 数量通常需要重启进程。
修改配置文件后发送 HUP 信号可以让 master 进程重载配置,但部分参数如 worker 数量可能需要完全重启服务才能生效,运维人员应在测试环境验证。
同步 worker 和异步 worker 有什么区别?
同步 worker 适合 CPU 密集型任务,异步 worker 适合 IO 密集型任务。
同步模式下每个请求独占一个 worker 直到完成,异步模式如 gevent 可以在等待 IO 时切换处理其他请求,从而提高单 worker 并发能力。
Nginx 反向代理时 worker 数量如何配合?
Nginx 的 worker 数量与 Gunicorn 的 worker 数量没有直接绑定关系,主要看后端处理能力。
Nginx 主要负责连接管理和静态文件,Gunicorn 负责 Python 代码执行,两者根据各自瓶颈独立配置即可。
参考来源
1. Gunicorn 官方文档 - Design: How many workers? (https://docs.gunicorn.org/en/stable/design.html#how-many-workers)