7.1 KiB
7.1 KiB
蓝绿部署计划
当前问题
部署时: 停止服务 → 上传新代码 → 重启服务 → 跑迁移
↑
此时有停机时间(约 3-5 秒)
单实例部署的风险:部署期间用户请求失败(502/503)。
概念澄清
蓝绿部署仅用于生产环境,开发环境保持单实例:
开发环境(dev.xmclassmate.top) — 单实例,无需蓝绿
└── 实例 :8080
└── 数据库 milkydata_dev
生产环境(xmclassmate.top) — 蓝绿部署
├── 蓝色实例 :4433(当前活动)
├── 绿色实例 :4434(空闲)
└── 数据库 milkydata(蓝绿共享,名称不变)
开发环境不需要蓝绿的原因:
| 原因 | 说明 |
|---|---|
| 停机时间可接受 | 开发环境只有开发者使用,重启 3-5 秒无影响 |
| 简化运维 | 少维护一套 systemd service 和 nginx 配置 |
| 快速迭代 | 直接 deploy.sh development 部署即可,无需切换步骤 |
生产环境使用蓝绿部署实现零停机发布。
数据库与蓝绿的关系
数据库名称不受蓝绿切换影响:
| 环境 | 数据库 | 蓝绿实例共同连接 |
|---|---|---|
| 开发 | milkydata_dev |
单实例,无需蓝绿 |
| 生产 | milkydata |
DATABASE_URL=postgres://.../milkydata |
两个蓝绿实例的 service 文件中 DATABASE_URL 配置为完全相同的值。切换蓝绿时只改端口,不改数据库连接。
域名与蓝绿的关系
蓝绿部署不改变域名访问方式,域名始终指向同一 OpenResty 实例:
用户访问 OpenResty(域名不变) 后端实例
xmclassmate.top ──→ xmclassmate.top ──→ :4433(蓝)或 :4434(绿)
切换时 OpenResty 内部的 proxy_pass 指向的目标端口变更,用户无感知:
切换前:xmclassmate.top ──→ proxy_pass 127.0.0.1:4433 ← 蓝色活动
切换后:xmclassmate.top ──→ proxy_pass 127.0.0.1:4434 ← 绿色活动
小程序前端的 env.ts 中 CURRENT_ENV=production 指向 xmclassmate.top,蓝绿切换时无需修改。
蓝绿部署架构(生产环境)
xmclassmate.top
│
OpenResty proxy
/ \
蓝色 (:4433 active) 绿色 (:4434 idle)
rust-backend-blue rust-backend-green
│ │
└──────────┬─────────────┘
↓
milkydata(共享数据库)
任何时候只有一个实例接收流量,另一个运行旧版本待命。
组件变更
新增 systemd service(生产环境)
/etc/systemd/system/
├── rust-backend-blue.service ← 端口 4433
└── rust-backend-green.service ← 端口 4434
每个 service 配置与现有 rust-backend.service 一致,仅端口和描述不同,且 DATABASE_URL 指向 milkydata。
新增 OpenResty 配置
由 1Panel 管理的 proxy 配置:
# /www/sites/xmclassmate.top/proxy/active-backend.conf
location ^~ / {
proxy_pass http://127.0.0.1:4433; # ← deploy.sh 切换此端口
...
}
切换时 sed 替换端口号,然后 nginx -s reload。
新增脚本
scripts/
├── deploy-blue-green.sh ← 蓝绿部署主脚本
└── switch-env.sh ← 手动切换/查看状态
部署流程(生产环境)
初始状态:蓝色(:4433)=active 绿色(:4434)=idle
步骤 1:部署到空闲环境(绿色)
① 编译新代码
② 上传二进制到绿色目录
③ systemctl restart rust-backend-green.service
④ 运行数据库迁移
步骤 2:验证绿色环境
curl http://127.0.0.1:4434/health
运行 9 项部署测试
步骤 3:切换流量
sed 修改 OpenResty proxy_pass → 127.0.0.1:4434
nginx -s reload
步骤 4:验证切换后
curl https://xmclassmate.top/health
结果:绿色(:4434)=active 蓝色(:4433)=idle
下次部署时部署到蓝色
切换脚本
# 查看当前活动环境
./scripts/switch-env.sh --status
# → 生产环境: 蓝色 (127.0.0.1:4433)
# 切换到绿色
./scripts/switch-env.sh --env prod --switch green
# → 修改 proxy_pass 127.0.0.1:4434
# → nginx -s reload
# → 验证健康检查
数据库迁移注意事项
蓝绿部署中两个实例共享同一数据库(milkydata),迁移脚本需要对新旧两个版本的代码都兼容:
| 迁移类型 | 兼容性 | 说明 |
|---|---|---|
CREATE TABLE |
✅ | 新旧代码都能运行 |
ADD COLUMN |
✅ | 需 DEFAULT 或允许 NULL |
RENAME COLUMN |
❌ | 旧代码仍查旧列名 |
DROP COLUMN |
❌ | 旧代码查询被删列 |
对于不兼容的迁移(如列重命名),需要三段式部署:
第 1 步:部署兼容双列名的代码(is_paid 和 is_member 同时支持)
第 2 步:执行迁移(重命名列)
第 3 步:部署只支持新列名的代码
当前代码已完成列重命名,若后续有类似变更需遵循此流程。
实施优先级
| 阶段 | 内容 | 工作量 |
|---|---|---|
| P1 | 创建两个 systemd service 模板(blue + green) | 小 |
| P2 | 编写 deploy-blue-green.sh + switch-env.sh |
中 |
| P3 | 实现 OpenResty proxy 配置切换 | 中 |
| P4 | 改造 deploy.sh 支持 --blue-green |
中 |
| P5 | 处理不兼容迁移的三段式部署文档 | 小 |
| P6 | 编写回滚文档 | 小 |
回滚
# 新环境有问题 → 立即切回旧环境
./scripts/switch-env.sh --env prod --switch blue
# 旧环境代码未变,即时恢复
# 修复问题后重新部署到空闲环境
生产上线待办
前端切换到生产域名前,需要依次完成以下步骤:
| # | 步骤 | 说明 | 执行方 |
|---|---|---|---|
| 1 | 生产库跑迁移 | 在 milkydata 上执行 010_rename_paid_fields.sql 等缺失迁移 |
服务器操作 |
| 2 | 准备生产 service 文件 | 填写 deploy/rust-backend-prod.service 中的实际值(JWT_SECRET、WECHAT_、ALIPAY_、DATABASE_URL) |
开发者 |
| 3 | 部署生产后端 | ./deploy.sh production 部署新代码到 :4433 |
服务器操作 |
| 4 | 修改前端 CURRENT_ENV |
env.ts 中 CURRENT_ENV = 'production'(当前已完成) |
开发者 |
| 5 | 上传小程序 | 微信开发者工具上传代码(此时连 xmclassmate.top) |
开发者 |
| 6 | 修改反向代理端口(如需蓝绿) | 1Panel 中调整 proxy_pass 指向新端口 |
服务器操作 |
端口映射汇总
| 环境 | 域名 | 数据库 | 当前端口 | 蓝绿备选端口 |
|---|---|---|---|---|
| 开发 | dev.xmclassmate.top |
milkydata_dev |
:8080 |
无(单实例) |
| 生产 | xmclassmate.top |
milkydata |
:4433 |
:4434 |
当前是否实施
当前项目规模(~100 日活),部署停机约 3-5 秒,实际影响可忽略。建议保留文档,当需要时再按 P1→P2 逐步实施。