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

228 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 蓝绿部署计划
## 当前问题
```
部署时: 停止服务 → 上传新代码 → 重启服务 → 跑迁移
此时有停机时间(约 3-5 秒)
```
单实例部署的风险部署期间用户请求失败502/503
## 概念澄清
蓝绿部署仅用于**生产环境**,开发环境保持单实例:
```
开发环境dev.xmclassmate.top — 单实例,无需蓝绿
└── 实例 :8080
└── 数据库 milkydata_dev当前与生产共用
生产环境xmclassmate.top — 蓝绿部署
├── 蓝色实例 :4433当前活动
├── 绿色实例 :4434空闲
└── 数据库 milkydata_dev蓝绿共享名称不变
```
> **当前状态**:生产环境使用 `milkydata_dev` 数据库(数据已从 `milkydata` 迁移)。开发与生产暂共用同一数据库,后续建议拆分。
开发环境不需要蓝绿的原因:
| 原因 | 说明 |
|------|------|
| 停机时间可接受 | 开发环境只有开发者使用,重启 3-5 秒无影响 |
| 简化运维 | 少维护一套 systemd service 和 nginx 配置 |
| 快速迭代 | 直接 `deploy.sh development` 部署即可,无需切换步骤 |
生产环境使用蓝绿部署实现零停机发布。
### 数据库与蓝绿的关系
数据库名称**不受蓝绿切换影响**
| 环境 | 数据库 | 蓝绿实例共同连接 |
|------|--------|----------------|
| 开发 | `milkydata_dev` | 单实例,无需蓝绿 |
| 生产 | `milkydata_dev` | `DATABASE_URL=postgres://.../milkydata_dev` |
两个蓝绿实例的 service 文件中 `DATABASE_URL` 配置为完全相同的值。切换蓝绿时只改端口,不改数据库连接。
## 域名与蓝绿的关系
蓝绿部署**不改变域名访问方式**,域名始终指向同一 OpenResty 实例:
```
用户访问 OpenResty域名不变 后端实例
xmclassmate.top ──→ xmclassmate.top ──→ :4433或 :4434绿
```
切换时 OpenResty 内部的 `proxy_pass` 指向的目标端口变更,**用户无感知**
```
切换前xmclassmate.top ──→ proxy_pass 127.0.0.1:4433 ← 蓝色活动
切换后xmclassmate.top ──→ proxy_pass 127.0.0.1:4434 ← 绿色活动
```
小程序前端的 `env.ts``CURRENT_ENV=production` 指向 `xmclassmate.top`,蓝绿切换时**无需修改**。
## 蓝绿部署架构(生产环境)
```
xmclassmate.top
OpenResty proxy
/ \
蓝色 (:4433 active) 绿色 (:4434 idle)
rust-backend-blue rust-backend-green
│ │
└──────────┬─────────────┘
milkydata_dev共享数据库
```
任何时候只有一个实例接收流量,另一个运行旧版本待命。
## 组件变更
### 新增 systemd service生产环境
```
/etc/systemd/system/
├── rust-backend-blue.service ← 端口 4433
└── rust-backend-green.service ← 端口 4434
```
每个 service 配置一致,仅端口和描述不同,`DATABASE_URL` 均指向 `milkydata_dev`
### 新增 OpenResty 配置
由 1Panel 管理的 proxy 配置:
```
# /www/sites/xmclassmate.top/proxy/active-backend.conf
location ^~ / {
proxy_pass http://127.0.0.1:4433; # ← deploy.sh 切换此端口
...
}
```
切换时 `sed` 替换端口号,然后 `nginx -s reload`
### 新增脚本
```
scripts/
├── deploy-blue-green.sh ← 蓝绿部署主脚本
└── switch-env.sh ← 手动切换/查看状态
```
## 部署流程(生产环境)
```
初始状态:蓝色(:4433)=active 绿色(:4434)=idle
步骤 1部署到空闲环境绿色
① 编译新代码
② 上传二进制到绿色目录
③ systemctl restart rust-backend-green.service
④ 运行数据库迁移
步骤 2验证绿色环境
curl http://127.0.0.1:4434/health
运行 9 项部署测试
步骤 3切换流量
sed 修改 OpenResty proxy_pass → 127.0.0.1:4434
nginx -s reload
步骤 4验证切换后
curl https://xmclassmate.top/health
结果:绿色(:4434)=active 蓝色(:4433)=idle
下次部署时部署到蓝色
```
## 切换脚本
```bash
# 查看当前活动环境
./scripts/switch-env.sh --status
# → 生产环境: 蓝色 (127.0.0.1:4433)
# 切换到绿色
./scripts/switch-env.sh --env prod --switch green
# → 修改 proxy_pass 127.0.0.1:4434
# → nginx -s reload
# → 验证健康检查
```
## 数据库迁移注意事项
蓝绿部署中两个实例共享同一数据库(`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 | 编写回滚文档 | 小 |
## 回滚
```bash
# 新环境有问题 → 立即切回旧环境
./scripts/switch-env.sh --env prod --switch blue
# 旧环境代码未变,即时恢复
# 修复问题后重新部署到空闲环境
```
## 生产上线待办
前端切换到生产域名前,需要依次完成以下步骤:
| # | 步骤 | 说明 | 执行方 |
|---|------|------|--------|
| 1 | **数据迁移** | `milkydata``milkydata_dev`**已完成** | ✅ 已执行 |
| 2 | **准备生产 service 文件** | 填写 `deploy/rust-backend-prod.service` 中的实际值JWT_SECRET、WECHAT_*、ALIPAY_*、DATABASE_URL | 开发者 |
| 3 | **部署生产后端** | `./deploy.sh production` 部署新代码到 `:4433`,数据库指向 `milkydata_dev` | 服务器操作 |
| 4 | **修改前端 `CURRENT_ENV`** | `env.ts``CURRENT_ENV = 'production'` | 开发者 |
| 5 | **上传小程序** | 微信开发者工具上传代码(此时连 `xmclassmate.top` | 开发者 |
| 6 | **修改反向代理端口**(如需蓝绿) | 1Panel 中调整 `proxy_pass` 指向新端口 | 服务器操作 |
### 数据库配置汇总
| 环境 | 域名 | 数据库 | 当前端口 | 蓝绿备选端口 |
|------|------|--------|---------|-------------|
| 开发 | `dev.xmclassmate.top` | `milkydata_dev` | `:8080` | 无(单实例) |
| 生产 | `xmclassmate.top` | `milkydata_dev` | `:4433` | `:4434` |
> 生产与开发目前共用 `milkydata_dev`。`milkydata` 作为历史数据源保留,不再更新。后续建议创建独立的生产数据库 `milkydata_prod`。
## 当前是否实施
当前项目规模(~100 日活),部署停机约 3-5 秒,实际影响可忽略。建议**保留文档**,当需要时再按 P1→P2 逐步实施。