From d7cb9a0f986a66af34b4652dca9533ed7acb86a9 Mon Sep 17 00:00:00 2001 From: milky0217 Date: Sat, 30 May 2026 09:23:29 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E8=93=9D=E7=BB=BF?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E8=AE=A1=E5=88=92(BLUE-GREEN-DEPLOY.md)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/BLUE-GREEN-DEPLOY.md | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 docs/BLUE-GREEN-DEPLOY.md diff --git a/docs/BLUE-GREEN-DEPLOY.md b/docs/BLUE-GREEN-DEPLOY.md new file mode 100644 index 0000000..02af743 --- /dev/null +++ b/docs/BLUE-GREEN-DEPLOY.md @@ -0,0 +1,168 @@ +# 蓝绿部署计划 + +## 当前问题 + +``` +部署时: 停止服务 → 上传新代码 → 重启服务 → 跑迁移 + ↑ + 此时有停机时间(约 3-5 秒) +``` + +单实例部署的风险:部署期间用户请求失败(502/503)。 + +## 蓝绿部署架构 + +``` + OpenResty(反向代理) + / \ + 蓝色环境 绿色环境 + 127.0.0.1:8081 127.0.0.1:8082 + rust-backend-blue rust-backend-green + | | + ↓ ↓ + 同一个 PostgreSQL(milkydata_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` 手动切换活动环境: + +```bash +# 查看当前活动环境 +./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` 模式: + +```bash +./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.sh` 和 `switch-blue-green.sh` | 中 | +| P3 | 编写 OpenResty 配置切换逻辑(1Panel API 或 直接改文件) | 中 | +| P4 | 改造现有 `deploy.sh` 支持 `--blue-green` | 中 | +| P5 | 处理不兼容迁移(列重命名等)的三段式部署 | 大 | +| P6 | 编写文档和回滚流程 | 小 | + +## 回滚流程 + +```bash +# 如果新环境有问题,立即切回旧环境 +./switch-blue-green.sh --switch blue + +# 旧环境仍然是部署前的版本,无需重新部署 +# 修复问题后重新走蓝绿部署流程 +``` + +## 建议 + +**当前项目规模(~100 日活)不需要蓝绿部署**。停机 3-5 秒的影响可以忽略。但如果是为了学习目的或为未来增长做准备,可以按 P1→P2 的顺序逐步实现。