diff --git a/docs/BLUE-GREEN-DEPLOY.md b/docs/BLUE-GREEN-DEPLOY.md index 02af743..d7de3b6 100644 --- a/docs/BLUE-GREEN-DEPLOY.md +++ b/docs/BLUE-GREEN-DEPLOY.md @@ -10,20 +10,42 @@ 单实例部署的风险:部署期间用户请求失败(502/503)。 +## 概念澄清 + +蓝绿部署是**同一环境内的两个实例**,不是跨环境: + +``` +开发环境(dev.xmclassmate.top) + ├── 蓝色实例 :8080(当前活动) + ├── 绿色实例 :8081(空闲) + └── 数据库 milkydata_dev(共享) + +生产环境(xmclassmate.top) + ├── 蓝色实例 :4433(当前活动) + ├── 绿色实例 :4434(空闲) + └── 数据库 milkydata(共享) +``` + +每个环境独立维护自己的蓝绿实例,互不干扰。 + ## 蓝绿部署架构 +以开发环境为例: + ``` - OpenResty(反向代理) + dev.xmclassmate.top + │ + OpenResty proxy / \ - 蓝色环境 绿色环境 - 127.0.0.1:8081 127.0.0.1:8082 + 蓝色 (:8080 active) 绿色 (:8081 idle) rust-backend-blue rust-backend-green | | - ↓ ↓ - 同一个 PostgreSQL(milkydata_dev) + └──────────┬─────────────┘ + ↓ + milkydata_dev(共享数据库) ``` -两个环境共享同一个数据库,但运行不同的代码版本。任何时候只有一个环境接收流量,另一个空闲。 +任何时候只有一个实例接收流量,另一个运行旧版本待命。 ## 组件变更 @@ -31,138 +53,125 @@ ``` /etc/systemd/system/ -├── rust-backend-blue.service ← 端口 8081 -└── rust-backend-green.service ← 端口 8082 +├── rust-backend-dev-blue.service ← 端口 8080 +└── rust-backend-dev-green.service ← 端口 8081 ``` -每个 service 文件与现有的 `rust-backend-dev.service` 结构一致,仅端口和描述不同。 +生产环境同理: + +``` +/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 -# 由 deploy.sh 自动切换 -# 蓝色环境 location ^~ / { - proxy_pass http://127.0.0.1:8081; + proxy_pass http://127.0.0.1:8080; # ← deploy.sh 切换此端口 ... } ``` -切换时只需替换这个文件中的端口号,然后 `nginx -s reload`。 +切换时 `sed` 替换端口号,然后 `nginx -s reload`。 ### 新增脚本 ``` scripts/ ├── deploy-blue-green.sh ← 蓝绿部署主脚本 -└── switch-blue-green.sh ← 手动切换蓝绿 +└── switch-env.sh ← 手动切换/查看状态 ``` ## 部署流程 ``` -部署前: 蓝色=active(:8081) 绿色=idle(:8082) +初始状态:蓝色(:8080)=active 绿色(:8081)=idle 步骤 1:部署到空闲环境(绿色) - cargo build --release - rsync 二进制 → 绿色目录 - systemctl restart rust-backend-green.service - run_migrations + ① 编译新代码 + ② 上传二进制到绿色目录 + ③ systemctl restart rust-backend-dev-green.service + ④ 运行数据库迁移 步骤 2:验证绿色环境 - curl http://127.0.0.1:8082/health - run_tests + curl http://127.0.0.1:8081/health + 运行 9 项部署测试 步骤 3:切换流量 - 修改 OpenResty proxy_pass → 127.0.0.1:8082 + sed 修改 OpenResty proxy_pass → 127.0.0.1:8081 nginx -s reload 步骤 4:验证切换后 curl https://dev.xmclassmate.top/health -部署后: 绿色=active(:8082) 蓝色=idle(:8081) - ← 下次部署时部署到蓝色 +结果:绿色(:8081)=active 蓝色(:8080)=idle + 下次部署时部署到蓝色 ``` ## 切换脚本 -`switch-blue-green.sh` 手动切换活动环境: - ```bash # 查看当前活动环境 -./switch-blue-green.sh --status -# → 当前活动: 蓝色 (127.0.0.1:8081) +./scripts/switch-env.sh --status +# → dev 环境: 蓝色 (127.0.0.1:8080) # 切换到绿色 -./switch-blue-green.sh --switch green -# → 修改 proxy_pass → 127.0.0.1:8082 +./scripts/switch-env.sh --env dev --switch green +# → 修改 proxy_pass 127.0.0.1:8081 # → nginx -s reload # → 验证健康检查 -# → 切换成功 -``` - -## deploy.sh 改造 - -现有 `deploy.sh` 增加 `--blue-green` 模式: - -```bash -./deploy.sh development --blue-green -``` - -自动检测空闲环境并部署到该环境: - -``` -1. 检查 8081 和 8082 哪个是空闲的 -2. 启动空闲环境的新版本 -3. 测试新版本 -4. 切换流量 -5. 停止旧版本 ``` ## 数据库迁移注意事项 -蓝绿部署中数据库是共享的,迁移需要考虑**向前兼容**: +蓝绿部署中两个实例共享同一数据库(同一环境内的 milkydata 或 milkydata_dev),迁移脚本需要对**新旧两个版本的代码都兼容**: -| 迁移类型 | 是否兼容 | 说明 | -|---------|---------|------| -| `CREATE TABLE` | ✅ 安全 | 新旧代码都能运行 | -| `ADD COLUMN` | ✅ 安全(需 DEFAULT 或 NULL) | 旧代码忽略新列 | -| `RENAME COLUMN` | ❌ **不兼容** | 旧代码查询旧列名会失败 | -| `DROP COLUMN` | ❌ 不兼容 | 旧代码查询被删列会失败 | +| 迁移类型 | 兼容性 | 说明 | +|---------|--------|------| +| `CREATE TABLE` | ✅ | 新旧代码都能运行 | +| `ADD COLUMN` | ✅ | 需 `DEFAULT` 或允许 `NULL` | +| `RENAME COLUMN` | ❌ | 旧代码仍查旧列名 | +| `DROP COLUMN` | ❌ | 旧代码查询被删列 | -对于不兼容的迁移(如列重命名 `010_rename_paid_fields.sql`),需要: +对于不兼容的迁移(如列重命名),需要**三段式部署**: ``` -1. 先部署兼容旧列名的新代码(两个列名都支持) -2. 再执行迁移重命名列 -3. 最后部署只支持新列名的代码 +第 1 步:部署兼容双列名的代码(is_paid 和 is_member 同时支持) +第 2 步:执行迁移(重命名列) +第 3 步:部署只支持新列名的代码 ``` -这称为**三段式迁移**,需要代码层面同时兼容新旧列名。当前 `010` 迁移不符合蓝绿条件,需要在代码中添加兼容层后再启用蓝绿。 +当前代码已完成列重命名,若后续有类似变更需遵循此流程。 -## 实施步骤 +## 实施优先级 | 阶段 | 内容 | 工作量 | |------|------|--------| -| P1 | 创建两个 systemd service 文件(blue + green) | 小 | -| P2 | 编写 `deploy-blue-green.sh` 和 `switch-blue-green.sh` | 中 | -| P3 | 编写 OpenResty 配置切换逻辑(1Panel API 或 直接改文件) | 中 | -| P4 | 改造现有 `deploy.sh` 支持 `--blue-green` | 中 | -| P5 | 处理不兼容迁移(列重命名等)的三段式部署 | 大 | -| P6 | 编写文档和回滚流程 | 小 | +| P1 | 创建两个 systemd service 模板(blue + green) | 小 | +| P2 | 编写 `deploy-blue-green.sh` + `switch-env.sh` | 中 | +| P3 | 实现 OpenResty proxy 配置切换 | 中 | +| P4 | 改造 `deploy.sh` 支持 `--blue-green` | 中 | +| P5 | 处理不兼容迁移的三段式部署文档 | 小 | +| P6 | 编写回滚文档 | 小 | -## 回滚流程 +## 回滚 ```bash -# 如果新环境有问题,立即切回旧环境 -./switch-blue-green.sh --switch blue +# 新环境有问题 → 立即切回旧环境 +./scripts/switch-env.sh --env dev --switch blue -# 旧环境仍然是部署前的版本,无需重新部署 -# 修复问题后重新走蓝绿部署流程 +# 旧环境代码未变,即时恢复 +# 修复问题后重新部署到空闲环境 ``` -## 建议 +## 当前是否实施 -**当前项目规模(~100 日活)不需要蓝绿部署**。停机 3-5 秒的影响可以忽略。但如果是为了学习目的或为未来增长做准备,可以按 P1→P2 的顺序逐步实现。 +当前项目规模(~100 日活),部署停机约 3-5 秒,实际影响可忽略。建议**保留文档**,当需要时再按 P1→P2 逐步实施。