Flask 自带的开发服务器(就是那个 app.run())只配在本地跑跑,真上了生产环境,分分钟给你颜色看——单进程、容易崩、扛不住并发。官方文档白纸黑字写着:这玩意儿不是让你部署用的。所以得换个正经的 WSGI 服务器。Gunicorn 是 Python 圈子里最顺手的方案之一,配置简单,文档全,社区里随便一搜全是案例。我在这篇文章里就跟你捋一遍,从零开始把 Gunicorn 装进你的 Flask 项目,顺便把那些容易踩的坑都指出来。
1. 安装 Gunicorn,就这么简单
假设你已经有了一个 Flask 项目,入口文件叫 app.py,里面有个 Flask 实例 app = Flask(__name__)。先装 Gunicorn:
pip install gunicorn
如果用了虚拟环境,记得进虚拟环境再装。没啥技术含量,下一步。
2. 跑起来看看效果
在项目根目录下执行:
gunicorn -w 4 app:app
app:app 的意思是“从 app.py 里找名叫 app 的那个 Flask 实例”,-w 4 表示开 4 个工作进程。默认绑在 127.0.0.1:8000,这时候你只能从本机访问(curl localhost:8000),浏览器访问不了,得配 Nginx 做反向代理。
想临时测试外网能不能通,可以改成监听所有网卡:
gunicorn -w 4 -b 0.0.0.0:8000 app:app
不过生产环境别这么干——直接把 Flask 暴露出去不安全,让 Nginx 在前面挡着才是正经做法。
3. worker 数量怎么定?有公式也有经验
-w 后面跟的数字决定同时能处理多少个请求。网上有个公式 (2 x CPU核心数) + 1,但别死磕。每个 worker 都是一个独立的 Python 进程,挺吃内存的。我一般先开 4 个,用 htop 盯着内存,够用就往上加,不够就减。如果你的应用大量涉及 I/O(比如调外部 API、读写数据库),可以考虑换 worker 类型,比如 -k gevent,能大幅提升并发能力。但要是普通 CRUD 项目,默认的 sync worker 足够了。
4. 让它变成系统服务,崩了自动重启
光在终端里跑不是长久之计——万一你退出登录,或者终端关了,Gunicorn 也就挂了。得用 systemd 把它管起来。
在 /etc/systemd/system/ 下新建一个文件,比如 myflask.service,内容大概长这样:
[Unit] Description=Gunicorn instance for My Flask App After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/你的项目绝对路径 Environment="PATH=/你的虚拟环境路径/bin" ExecStart=/你的虚拟环境路径/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app Restart=always [Install] WantedBy=multi-user.target
写完保存,然后执行:
sudo systemctl daemon-reload sudo systemctl start myflask sudo systemctl enable myflask # 开机自启
之后用 systemctl status myflask 看状态,journalctl -u myflask 看日志。再也不用担心进程意外退出了。
5. 搭配 Nginx,让服务更安全
Gunicorn 只负责跑 Python 代码,静态文件、HTTPS、负载均衡这些活儿得交给 Nginx。Nginx 配置里加一段代理转发:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias /你的项目路径/static;
}
}
这样用户访问你的域名,Nginx 把请求转给 Gunicorn,静态文件直接由 Nginx 处理,效率高得多。别忘了重启 Nginx。
6. 一点关于配置的碎碎念
绑定地址
生产环境 Gunicorn 应该只监听 127.0.0.1,这样只有本机的 Nginx 能访问,外网进不来,安全。
超时设置
如果你的某个接口处理时间特别长(比如生成报表),可能超过 Gunicorn 默认的 30 秒超时,可以用 -t 120 改成 120 秒。
日志记录
Gunicorn 默认把访问日志打到 stdout,可以用 --access-logfile 指定文件路径,方便排查问题。
7. 踩坑记录
- 虚拟环境路径写错:systemd 里
Environment和ExecStart的路径必须用绝对路径,少一个斜杠都起不来。 - 端口冲突:如果 8000 被别的程序占了,换一个端口或者先
lsof -i:8000看看是谁。 - worker 炸弹:
-w设得太大,内存直接爆掉,监控一下实际负载,别贪心。 - 静态文件 404:检查 Nginx 的
alias路径,权限对不对。
8. 最后说两句
Gunicorn + Nginx 这套组合,Python 圈里跑了好多年,稳得很。一开始配起来可能有点懵,但配好了之后,一个项目接着一个项目复用,效率越来越高。
如果你用的是 Docker,那套路又不一样,但核心还是 Gunicorn。先把这一套跑通,再学容器化也不迟。
反正我每个 Flask 项目上线都是这套流程,没出过大问题。你可以按步骤试试,遇到问题搜一下,基本都有答案。