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

4.5 KiB
Raw Blame History

蓝绿部署计划

当前问题

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

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

蓝绿部署架构

                    OpenResty反向代理
                    /              \
             蓝色环境                绿色环境
        127.0.0.1:8081           127.0.0.1:8082
        rust-backend-blue        rust-backend-green
               |                        |
               ↓                        ↓
           同一个 PostgreSQLmilkydata_dev

两个环境共享同一个数据库,但运行不同的代码版本。任何时候只有一个环境接收流量,另一个空闲。

组件变更

新增 systemd service

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

每个 service 文件与现有的 rust-backend-dev.service 结构一致,仅端口和描述不同。

新增 OpenResty 配置

# /www/sites/dev.xmclassmate.top/proxy/active-backend.conf
# 由 deploy.sh 自动切换

# 蓝色环境
location ^~ / {
    proxy_pass http://127.0.0.1:8081;
    ...
}

切换时只需替换这个文件中的端口号,然后 nginx -s reload

新增脚本

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

部署流程

部署前: 蓝色=active(:8081)  绿色=idle(:8082)

步骤 1部署到空闲环境绿色
  cargo build --release
  rsync 二进制 → 绿色目录
  systemctl restart rust-backend-green.service
  run_migrations

步骤 2验证绿色环境
  curl http://127.0.0.1:8082/health
  run_tests

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

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

部署后: 绿色=active(:8082)  蓝色=idle(:8081)
           ← 下次部署时部署到蓝色

切换脚本

switch-blue-green.sh 手动切换活动环境:

# 查看当前活动环境
./switch-blue-green.sh --status
# → 当前活动: 蓝色 (127.0.0.1:8081)

# 切换到绿色
./switch-blue-green.sh --switch green
# → 修改 proxy_pass → 127.0.0.1:8082
# → nginx -s reload
# → 验证健康检查
# → 切换成功

deploy.sh 改造

现有 deploy.sh 增加 --blue-green 模式:

./deploy.sh development --blue-green

自动检测空闲环境并部署到该环境:

1. 检查 8081 和 8082 哪个是空闲的
2. 启动空闲环境的新版本
3. 测试新版本
4. 切换流量
5. 停止旧版本

数据库迁移注意事项

蓝绿部署中数据库是共享的,迁移需要考虑向前兼容

迁移类型 是否兼容 说明
CREATE TABLE 安全 新旧代码都能运行
ADD COLUMN 安全(需 DEFAULT 或 NULL 旧代码忽略新列
RENAME COLUMN 不兼容 旧代码查询旧列名会失败
DROP COLUMN 不兼容 旧代码查询被删列会失败

对于不兼容的迁移(如列重命名 010_rename_paid_fields.sql),需要:

1. 先部署兼容旧列名的新代码(两个列名都支持)
2. 再执行迁移重命名列
3. 最后部署只支持新列名的代码

这称为三段式迁移,需要代码层面同时兼容新旧列名。当前 010 迁移不符合蓝绿条件,需要在代码中添加兼容层后再启用蓝绿。

实施步骤

阶段 内容 工作量
P1 创建两个 systemd service 文件blue + green
P2 编写 deploy-blue-green.shswitch-blue-green.sh
P3 编写 OpenResty 配置切换逻辑1Panel API 或 直接改文件)
P4 改造现有 deploy.sh 支持 --blue-green
P5 处理不兼容迁移(列重命名等)的三段式部署
P6 编写文档和回滚流程

回滚流程

# 如果新环境有问题,立即切回旧环境
./switch-blue-green.sh --switch blue

# 旧环境仍然是部署前的版本,无需重新部署
# 修复问题后重新走蓝绿部署流程

建议

当前项目规模(~100 日活)不需要蓝绿部署。停机 3-5 秒的影响可以忽略。但如果是为了学习目的或为未来增长做准备,可以按 P1→P2 的顺序逐步实现。