
上一篇我们加了 JSON API本地用python manage.py或flask run就能跑。自己开发没问题但 不能直接把这套方式原封不动丢到公网服务器。这一篇做一件事用 Gunicorn 把 Flask 应用跑成「生产模式」并知道 Nginx 大概怎么接在前面。例子仍是通用的Note备忘录项目不涉及任何真实业务。1. 学完后你能做什么说清楚app.run()和 Gunicorn 的区别用一条命令启动gunicorn -w 4 -b 127.0.0.1:5000 app:app知道 worker 数量 怎么估上线前检查FLASK_DEBUG0、SECRET_KEY、数据库理解 Nginx 反代 在整体架构里干什么用 systemd 让进程挂了自动拉起入门版2. 为什么开发用的app.run()不适合生产manage.py里常见写法from app import appif __name__ __main__:app.run()Flask 自带的开发服务器特点开发生产并发弱单进程为主需要多 worker安全有调试便利不适合暴露公网要关 DEBUG稳定性改代码自动重载要常驻、崩溃重启性能够用扛不住真实流量官方文档也写明不要用 Werkzeug 开发服务器部署生产。开发app.run(debugTrue)方便。上线换 Gunicorn或 uWSGI、Waitress 等Flask 只负责「应用对象」不管进程模型。3. Gunicorn 是什么GunicornGreen Unicorn是 Python 常用的 WSGI HTTP 服务器浏览器 / curl│▼Nginx可选443/80│▼Gunicorn多 worker 进程│▼Flask app 对象你的路由、视图你写的app.route不用改换的是 最外层怎么接 HTTP。4. 安装与第一条启动命令虚拟环境里pip install gunicorn在项目根目录有app/包、manage.py的那层# 先加载第十二篇的环境变量export FLASK_DEBUG0export SECRET_KEY生产环境随机长字符串# export DATABASE_URL...gunicorn -w 4 -b 127.0.0.1:5000 app:app参数含义参数含义-w 44 个 worker 进程-b 127.0.0.1:5000监听本机 5000 端口app:app模块app里的变量app即app/__init__.py里的 Flask 实例浏览器访问http://127.0.0.1:5000/notes/或你的首页路由应能打开。app:app怎么记app:app│ └── Flask 实例的名字通常也叫 app└── Python 包名app/ 文件夹若实例叫application就写app:application。5. worker 数量怎么选经验公式CPU 密集型偏少、I/O 多可略多workers 2 × CPU 核数 1例如 2 核 →-w 5左右。入门项目 24 个 往往够用别一上来开几十个。每个 worker 是 独立进程占一份内存。内存紧张时 worker 要减。6. 上线前配置清单接第十二篇服务器上的环境变量如/etc/myapp.env至少确认FLASK_DEBUG0SECRET_KEY一串足够长的随机值DATABASE_URLmysqlpymysql://user:pass127.0.0.1/dbname# 或 SQLitesqlite:////var/www/myapp/instance/app.db务必关闭调试FLASK_DEBUG1时错误页可能 泄露代码和变量部分场景下还有 远程执行风险视 Flask/Werkzeug 版本而定加载方式set -a source /etc/myapp.env set agunicorn -w 4 -b 127.0.0.1:5000 app:appHTTPS 站点若用 Session Cookie还可加SESSION_COOKIE_SECURE1仅 HTTPS 下浏览器才带 Cookie。7. 数据库迁移别忘了第七篇用过 Flask-Migrate。部署新版本代码后cd /var/www/myappsource .venv/bin/activateset -a source /etc/myapp.env set aexport FLASK_APPappflask db upgrade先迁移、再重启 Gunicorn避免代码要新字段、表还没改。8. 静态文件怎么办备忘录项目的 CSS、JS 在app/static/Flask 开发时会自动提供。生产常见两种做法方式说明Nginx 直接托管 static快减轻 Python 压力推荐仍由 Flask/Gunicorn 提供小项目、流量低可以先这样Nginx 示例片段静态走文件其余走 Gunicornlocation /static/ {alias /var/www/myapp/app/static/;}location / {proxy_pass http://127.0.0.1:5000;proxy_set_header Host $host;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;}入门阶段先全部proxy_pass到 Gunicorn 也能跑访问量上来再拆 static。9. 为什么要 Nginx 挡在前面Gunicorn 监听127.0.0.1:5000不直接暴露公网 时Nginx 处理 80/443、HTTPS 证书可配 限流、gzip、上传大小多站点同一台机器时更好管架构用户 → https://notes.example.com│▼Nginx :443│▼Gunicorn 127.0.0.1:5000│▼Flask app暂时没域名时可-b 0.0.0.0:5000先验证记得防火墙只开必要端口不要长期裸奔。10. 用 systemd 常驻进程挂了自动起来手动 SSH 里跑 Gunicorn断开 SSH 进程可能就没了。用 systemd 托管/etc/systemd/system/myapp.service[Unit]DescriptionNote Flask (Gunicorn)Afternetwork.target[Service]Userwww-dataGroupwww-dataWorkingDirectory/var/www/myappEnvironmentFile/etc/myapp.envExecStart/var/www/myapp/.venv/bin/gunicorn -w 4 -b 127.0.0.1:5000 app:appRestartalways[Install]WantedBymulti-user.target启用sudo systemctl daemon-reloadsudo systemctl enable myappsudo systemctl start myappsudo systemctl status myapp改代码后git pullflask db upgrade # 若有表结构变更sudo systemctl restart myapp11. 日志与排错Gunicorn 默认日志在终端。生产可指定文件gunicorn -w 4 -b 127.0.0.1:5000 app:app \--access-logfile /var/log/myapp/access.log \--error-logfile /var/log/myapp/error.log常见问题现象可能原因502 Bad GatewayGunicorn 没起来、端口不对静态 404Nginxalias路径错改代码不生效没 restart systemd数据库连不上DATABASE_URL、MySQL 权限、防火墙Session 登录丢SECRET_KEY变了、Cookie Secure 与 HTTP 混用12. 开发 vs 生产对照本地开发生产启动python manage.py/flask rungunicorn app:appDEBUG可开必须关进程1 个多 worker端口5000 本机127.0.0.1 Nginx配置.env/etc/myapp.env迁移随手flask db upgrade部署流程里固定一步13. 新手常踩的 5 个坑生产仍用app.run(debugTrue)— 换 Gunicorn关 DEBUG。gunicorn manage:app与app:app混用 — 以你项目里 Flask 实例在哪定义 为准常见是from app import app→app:app。没做flask db upgrade就重启 — 新代码访问新字段会 500。SECRET_KEY 每次部署随机变 — 所有用户 Session 失效要固定存环境变量。worker 开太多 — 内存爆掉反而更慢。14. 小结记住五件事app.run()只用于开发生产用 Gunicorngunicorn -w 4 -b 127.0.0.1:5000 app:appFLASK_DEBUG0 强SECRET_KEY前面加 Nginx 做 HTTPS 和反代入门可先全量 proxysystemd flask db upgrade组成最小部署闭环十四篇下来你已经走完写功能 → 分层 → 配置外置 → JSON API → 上线跑起来。