Flask项目不能直接用flask run上生产,因其启动的是Werkzeug单线程开发服务器,无并发处理、无超时控制、无守护进程、不支持静态文件与负载均衡,且debug=True会暴露调试信息和堆栈,存在严重安全与性能风险。

Flask项目直接用 flask run 为什么不能上生产
因为 flask run 启动的是 Werkzeug 自带的开发服务器,单进程、无并发处理能力、不支持守护进程、没有自动重启机制,还暴露了调试信息——线上一压就崩,日志乱成一团,连基本的请求超时都扛不住。
真正能跑生产的方案是:Flask 应用由 Gunicorn 管理多个工作进程,再由 Nginx 做反向代理,负责静态文件、SSL 终止、连接复用和请求分发。
-
Gunicorn只管 Python 进程,不处理 HTTP 协议细节(比如 HTTPS、gzip、缓存头) -
Nginx不碰 Python 代码,只做它擅长的事:高并发接入、静态资源服务、负载均衡前置 - 两者通过 Unix socket(推荐)或 TCP 端口通信,
Gunicorn监听本地地址,Nginx把用户请求转发过去
怎么配置 Gunicorn 启动 Flask 并保持后台运行
别用 nohup gunicorn ... & 这种裸奔方式——进程容易意外退出,没日志轮转,升级时难平滑重启。
推荐用 systemd 管理,写一个 /etc/systemd/system/myflask.service:
立即学习“Python免费学习笔记(深入)”;
[Unit] Description=My Flask App with Gunicorn After=network.target [Service] Type=simple User=www-data Group=www-data WorkingDirectory=/var/www/myflask ExecStart=/var/www/myflask/venv/bin/gunicorn --bind unix:/var/run/myflask.sock --workers 3 --worker-class sync --timeout 30 --keep-alive 5 --preload app:app Restart=always RestartSec=10 KillSignal=SIGTERM StandardOutput=append:/var/log/myflask/access.log StandardError=append:/var/log/myflask/error.log SyslogIdentifier=myflask [Install] WantedBy=multi-user.target
注意几个关键点:
-
--bind unix:/var/run/myflask.sock:用 Unix socket 比 TCP 更快更安全,记得给/var/run下 socket 文件加权限(chmod 755 /var/run,且www-data要有写权限) -
--workers 3:一般设为 CPU 核心数 × 2 + 1,但 Flask 是同步 I/O,别盲目堆 worker,先从 3 开始压测 -
--preload:让 Gunicorn 先加载一次应用再 fork 子进程,避免每个 worker 都重复初始化数据库连接等操作 -
Restart=always和RestartSec=10:保证崩溃后自动拉起,但别设太短,防止启动失败反复刷日志
Nginx 怎么正确反向代理到 Gunicorn 的 socket
很多人卡在 Nginx 报 502 Bad Gateway,八成是权限或路径问题——Nginx 默认以 www-data 用户运行,但 socket 文件可能属于 root 或其他用户。
在 /etc/nginx/sites-available/myflask 中配好后,软链到 sites-enabled,核心 location 块要这样写:
server {
listen 80;
server_name example.com;
location / {
include proxy_params;
proxy_pass http://unix:/var/run/myflask.sock;
proxy_redirect off;
proxy_buffering on;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /static {
alias /var/www/myflask/static;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
重点检查这几项:
-
proxy_pass http://unix:/var/run/myflask.sock:协议必须写http://,哪怕后面是 socket 路径,这是 Nginx 的固定语法 -
include proxy_params:这个文件里定义了常用 header(如X-Forwarded-For),漏掉会导致 Flask 拿不到真实 IP -
location /static:别让 Flask 处理静态文件,Nginx 直接 serve,否则浪费 Gunicorn worker - 改完配置后执行
sudo nginx -t测试语法,再sudo systemctl reload nginx
部署后访问 502 或 404 的常见排查顺序
别急着重装,按这个顺序快速定位:
- 查
Gunicorn是否真在跑:sudo systemctl status myflask,看 Active 状态和最近日志(journalctl -u myflask -n 50 -f) - 确认 socket 文件是否存在且可读:
ls -l /var/run/myflask.sock,如果不存在,说明 Gunicorn 没成功 bind;如果存在但属主不是www-data,Nginx 就连不上 - 手动用 curl 测试 socket:
curl --unix-socket /var/run/myflask.sock http://localhost/,能通说明 Gunicorn 没问题,问题出在 Nginx 层 - 看 Nginx 错误日志:
sudo tail -f /var/log/nginx/error.log,里面常有具体原因,比如connect() to unix:/var/run/myflask.sock failed (13: Permission denied) - Flask 代码里别依赖
os.getcwd()或相对路径读配置/模板——systemd启动时工作目录不确定,一律用绝对路径或os.path.dirname(__file__)定位
最易忽略的是 socket 权限和 proxy_params 缺失,这两项占线上 502 问题的七成以上。


















