Files
asd-backend/docs/BLUE-GREEN-DEPLOY.md
2026-07-13 18:30:38 +08:00

6.5 KiB
Raw Blame History

蓝绿部署(新服务器)

服务器47.109.203.92 (Aliyun, Debian 13) nginx:原生 nginx非 Docker/OpenResty PostgreSQLDocker 容器 postgres:17.6-alpine 部署用户deploy(有 sudo 权限)

域名与环境映射

域名                 环境        后端端口        数据库
────────────────────────────────────────────────────
dev.xmclassmate.top  开发/测试   :8080          milkydata_dev
xmclassmate.top      生产        :4433 / :4434  milkydata

原则:两个域名永远指向各自的环境,不互换。生产采用蓝绿部署实现零停机。

当前问题

单实例部署时存在停机时间:

停止服务 → 上传新代码 → 重启服务 → 跑迁移
           ↑
     3-5 秒停机

开发环境dev.xmclassmate.top

保持单实例,无需蓝绿:

dev.xmclassmate.top
       │
  nginx → :8080单实例
       │
  milkydata_dev

开发环境不需要蓝绿的原因:

原因 说明
停机时间可接受 仅开发者使用,重启 3-5 秒无影响
简化运维 少维护一套 systemd service
快速迭代 直接 deploy.sh development 部署

生产环境xmclassmate.top— 蓝绿部署

架构

xmclassmate.top
       │
  nginx proxy直接路由
    /          \
 蓝色 :4433    绿色 :4434
(active)      (idle)
    \          /
  milkydata共享

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

组件

systemd service

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

两个 service 的 DATABASE_URL 都指向 milkydata,仅端口不同。

nginx proxy 配置:

# /www/sites/xmclassmate.top/proxy/root.conf
location ^~ / {
    proxy_pass https://127.0.0.1:4433;  # deploy.sh 切换此端口
}

生产环境使用 HTTPS proxyproxy_pass https://...),因为后端自身处理 TLS。

切换时 sed 替换端口,sudo nginx -s reload

部署流程

初始:蓝色(:4433)=active  绿色(:4434)=idle

步骤 1部署到空闲环境绿色
  ① cargo build --release
  ② rsync 二进制 → 绿色目录
  ③ systemctl restart rust-backend-green.service
  ④ 运行数据库迁移

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

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

步骤 4验证
  curl https://xmclassmate.top/health

结果:绿色(:4434)=active  蓝色(:4433)=idle
      下次部署到蓝色

切换脚本

./scripts/switch-env.sh --switch green
# 或切回蓝色
./scripts/switch-env.sh --switch blue
# 查看当前状态
./scripts/switch-env.sh --status

回滚

./scripts/switch-env.sh --env prod --switch blue  # 即时恢复旧版本

旧环境代码未变,无需重新部署。

数据库

环境 数据库 说明
开发 milkydata_dev 单实例直连
生产 milkydata 蓝绿实例共享,名称不变

生产库 milkydata,开发库 milkydata_dev,两者独立。

限制与注意事项

1. 部署只能部署到非活动端口

每次部署必须部署到当前空闲的环境,绝不能直接部署到正在接收流量的端口。

正确流程:
  Green(:4434) 活动中 → 部署到 Blue(:4433) → 测试 → 切到 Blue(:4433)
  Blue(:4433)  活动中 → 部署到 Green(:4434) → 测试 → 切到 Green(:4434)

错误:
  Green(:4434) 活动中 → 直接部署到 Green(:4434)  ← ❌ 会产生停机

原因:部署过程涉及服务重启(~3-5 秒),如果直接部署到活动中环境, 会导致在此期间的用户请求失败。

2. 代码只能通过 deploy.sh 部署

禁止手动 rsync + systemctl restart 部署。必须使用统一脚本:

# 正确
./deploy.sh production --target blue --yes

# 错误
cargo build --release && rsync ... systemctl restart  ← ❌

原因

  • 自动备份旧版本,支持回滚
  • 自动运行数据库迁移
  • 自动验证服务健康
  • 自动切换代理(零停机)
  • 自动记录部署日志
  • 跳过手动操作的遗漏风险

3. 部署后先验证再切换

deploy.sh --skip-tests 跳过了部署后的自动测试。建议仅在开发/快速迭代时使用, 生产环境应让测试跑完再切换。

4. 数据库兼容性(迁移注意事项)

蓝绿共享数据库,迁移需向前兼容:

迁移类型 兼容 说明
CREATE TABLE 新旧代码均可运行
ADD COLUMN DEFAULT 或允许 NULL
RENAME COLUMN 旧代码查询旧列名会失败
DROP COLUMN 旧代码查询被删列会失败

不兼容的迁移需要三段式部署。

实施优先级

阶段 内容 工作量
P1 创建 blue + green 两个 systemd service
P2 编写 deploy-blue-green.sh + switch-env.sh
P3 实现 OpenResty proxy 配置切换
P4 改造 deploy.sh 支持 --blue-green
P5 不兼容迁移的三段式部署文档
P6 回滚文档

生产上线待办

# 步骤 说明 状态
1 数据迁移 已完成
2 准备生产 service 文件 已完成
3 部署新代码到 :4433:4434 已完成
4 env.tsCURRENT_ENV = 'production' 已完成
5 微信开发者工具上传小程序 已完成
6 确认 nginx proxy_pass 指向 :4433 已完成

实施状态

蓝绿部署已实施并运行中:

组件 状态
Blue service (:4433) 运行中,当前活跃
Green service (:4434) 运行中,待命中
deploy.sh production --target blue/green 已支持
switch-env.sh --switch blue/green 自动切换 nginx proxy
nginx proxy 指向活动中环境

下次部署流程

# 1. 查看当前活动中环境
./scripts/switch-env.sh --status

# 2. 部署到空闲环境(假设 green 活动中 → 部署到 blue
./deploy.sh production --target blue --yes

# 3. 部署完成后自动切换流量到 blue
# deploy.sh 自动调用 switch-env.sh --switch blue