Files
asd-backend/docs/BLUE-GREEN-DEPLOY.md

6.6 KiB
Raw Blame History

蓝绿部署计划

当前问题

部署时: 停止服务 → 上传新代码 → 重启服务 → 跑迁移
                    ↑
              此时有停机时间(约 3-5 秒)

单实例部署的风险部署期间用户请求失败502/503

概念澄清

蓝绿部署是同一环境内的两个实例,不是跨环境:

开发环境dev.xmclassmate.top
  ├── 蓝色实例 :8080当前活动
  ├── 绿色实例 :8081空闲
  └── 数据库 milkydata_dev共享

生产环境xmclassmate.top
  ├── 蓝色实例 :4433当前活动
  ├── 绿色实例 :4434空闲
  └── 数据库 milkydata共享

每个环境独立维护自己的蓝绿实例,互不干扰。

蓝绿部署架构

以开发环境为例:

                    dev.xmclassmate.top
                           │
                    OpenResty proxy
                    /              \
         蓝色 (:8080 active)     绿色 (:8081 idle)
        rust-backend-blue        rust-backend-green
               |                        |
               └──────────┬─────────────┘
                          ↓
                    milkydata_dev共享数据库

任何时候只有一个实例接收流量,另一个运行旧版本待命。

域名与蓝绿的关系

蓝绿部署不改变域名访问方式,域名始终指向同一 OpenResty 实例:

用户访问           OpenResty域名不变           后端实例
dev.xmclassmate.top  ──→  dev.xmclassmate.top  ──→  :8080或 :8081绿
xmclassmate.top      ──→  xmclassmate.top      ──→  :4433或 :4434绿

切换时 OpenResty 内部的 proxy_pass 指向的目标端口变更,用户无感知

切换前dev.xmclassmate.top  ──→  proxy_pass 127.0.0.1:8080  ← 蓝色活动
切换后dev.xmclassmate.top  ──→  proxy_pass 127.0.0.1:8081  ← 绿色活动

小程序前端的 env.tsCURRENT_ENV 指向的域名(dev.xmclassmate.topxmclassmate.top无需修改

组件变更

新增 systemd service

/etc/systemd/system/
├── rust-backend-dev-blue.service    ← 端口 8080
└── rust-backend-dev-green.service   ← 端口 8081

生产环境同理:

/etc/systemd/system/
├── rust-backend-blue.service        ← 端口 4433
└── rust-backend-green.service       ← 端口 4434

每个 service 配置与现有文件一致,仅端口和描述不同,且 DATABASE_URL 指向同一数据库。

新增 OpenResty 配置

由 1Panel 管理的 proxy 配置:

# /www/sites/dev.xmclassmate.top/proxy/active-backend.conf

location ^~ / {
    proxy_pass http://127.0.0.1:8080;  # ← deploy.sh 切换此端口
    ...
}

切换时 sed 替换端口号,然后 nginx -s reload

新增脚本

scripts/
├── deploy-blue-green.sh          ← 蓝绿部署主脚本
└── switch-env.sh                 ← 手动切换/查看状态

部署流程

初始状态:蓝色(:8080)=active  绿色(:8081)=idle

步骤 1部署到空闲环境绿色
  ① 编译新代码
  ② 上传二进制到绿色目录
  ③ systemctl restart rust-backend-dev-green.service
  ④ 运行数据库迁移

步骤 2验证绿色环境
  curl http://127.0.0.1:8081/health
  运行 9 项部署测试

步骤 3切换流量
  sed 修改 OpenResty proxy_pass → 127.0.0.1:8081
  nginx -s reload

步骤 4验证切换后
  curl https://dev.xmclassmate.top/health

结果:绿色(:8081)=active  蓝色(:8080)=idle
      下次部署时部署到蓝色

切换脚本

# 查看当前活动环境
./scripts/switch-env.sh --status
# → dev 环境: 蓝色 (127.0.0.1:8080)

# 切换到绿色
./scripts/switch-env.sh --env dev --switch green
# → 修改 proxy_pass 127.0.0.1:8081
# → nginx -s reload
# → 验证健康检查

数据库迁移注意事项

蓝绿部署中两个实例共享同一数据库(同一环境内的 milkydata 或 milkydata_dev迁移脚本需要对新旧两个版本的代码都兼容

迁移类型 兼容性 说明
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 dev --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.tsCURRENT_ENV = 'production'(当前已完成) 开发者
5 上传小程序 微信开发者工具上传代码(此时连 xmclassmate.top 开发者
6 修改反向代理端口(如需蓝绿) 1Panel 中调整 proxy_pass 指向新端口 服务器操作

端口映射汇总

环境 域名 当前端口 蓝绿备选端口
开发 dev.xmclassmate.top :8080 :8081
生产 xmclassmate.top :4433 :4434

当前是否实施

当前项目规模(~100 日活),部署停机约 3-5 秒,实际影响可忽略。建议保留文档,当需要时再按 P1→P2 逐步实施。