必须删除所有 app.run(),否则 gunicorn 不生效;合理设置 --workers 数量并匹配 worker-class;显式加载 flask 配置;nginx 必须透传 x-real-ip、x-forwarded-for、x-forwarded-proto 头。

删掉所有 app.run(),否则 Gunicorn 根本不生效——这是上线前最常被跳过的一步,也是压测时发现“并发没提升”的根本原因。
必须删干净所有 app.run()
Gunicorn 启动时直接导入模块并调用 WSGI callable(比如 app),完全绕过 if __name__ == '__main__': app.run()。如果你没删它:
- 本地运行
python app.py时,实际跑的是 Werkzeug 开发服务器,日志里会带 WARNING:「This is a development server. Do not use it in a production environment.」 - 用
gunicorn app:app启动时,app.run()被忽略,但残留代码容易误导你认为“配置已生效” - 检查所有可能被直接执行的文件:
app.py、main.py、run.py、manage.py,把所有app.run(...)行注释或删除
--workers 数量不是拍脑袋定的
盲目设 --workers 16 在 4 核机器上,反而导致 GIL 争抢、内存暴涨、响应变慢。CPython 的全局解释器锁让多进程对 CPU 密集型任务收益有限。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- CPU 密集型(如图像处理、数值计算):用默认
--worker-class sync,--workers设为2 * CPU核心数 + 1(例如 4 核 →--workers 9) - I/O 密集型(如频繁查数据库、调外部 API):可试
--worker-class gevent,但必须在应用最开头加from gevent import monkey; monkey.patch_all(),且要额外装gevent - 不确定类型或刚上线:先用
--workers 4 --worker-class sync跑通,再压测调整 - 启动时加
--log-level info,日志里会明确打出「Booting worker with pid XXX」,数一下实际 worker 数量,避免“以为起了 8 个,其实只起了 1 个”
Flask 配置不会自动加载,必须显式触发
Gunicorn 不解析 .env 或 config.py,它只管启动 WSGI 应用。你代码里写的 DEBUG=True 或 SECRET_KEY,如果没在应用初始化阶段显式载入,线上就还是默认值。
- 推荐在入口模块(如
app.py)中显式加载:app.config.from_object('config.ProdConfig') - 或用绝对路径加载:
app.config.from_pyfile(os.path.join(os.path.dirname(__file__), 'config.py')) - 别依赖
FLASK_ENV=production——这个环境变量从 Flask 2.3 起已废弃,--env FLASK_ENV=production对 Gunicorn 无效,也不影响 Flask 行为
Nginx 反代不透传头,Flask 就拿不到真实 IP 和协议
只写 proxy_pass http://127.0.0.1:8000; 是不够的。Flask 生成重定向 URL、记录日志、判断是否 HTTPS 时,全靠这些头。
- 必须在 Nginx 配置里加上:
proxy_set_header X-Real-IP $remote_addr;、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;、proxy_set_header X-Forwarded-Proto $scheme; - 否则
request.remote_addr拿到的是127.0.0.1,url_for(..., _external=True)生成的链接是http://而非https:// - 如果用了
gevent或eventlet,还要确保 Nginx 的proxy_buffering off;和超时设置匹配,否则长连接可能被意外断开
真正卡住人的地方往往不在命令行参数本身,而在配置加载顺序、头信息透传、以及 worker 类型与业务模型的错配——比如给一个加载大模型的服务配了 --workers 8,结果每个 worker 都把模型加载进内存,直接 OOM。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










