Flask 项目用 Gunicorn 部署,告别拉跨的app.run()

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 项目上线都是这套流程,没出过大问题。你可以按步骤试试,遇到问题搜一下,基本都有答案。

You May Also Like

About the Author: 一块自由的砖

码农一个,一块自由勤恳的砖,哪里需要哪里搬!( ̄▽ ̄)"