上传源代码版本
This commit is contained in:
513
deployment/DEPLOYMENT_GUIDE.md
Normal file
513
deployment/DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,513 @@
|
||||
# 固定端口蓝绿部署完整指南
|
||||
|
||||
## 架构概述
|
||||
|
||||
本方案采用**固定端口蓝绿部署**策略,允许在不中断客户端访问的情况下更新应用程序:
|
||||
|
||||
```
|
||||
网络流量 (Nginx)
|
||||
↓
|
||||
→ 当前活跃实例 (蓝/绿) [端口固定: 5000 或 5001]
|
||||
↓
|
||||
应用程序处理
|
||||
```
|
||||
|
||||
### 关键特点
|
||||
- **蓝实例**:固定运行在 **端口 5000**
|
||||
- **绿实例**:固定运行在 **端口 5001**
|
||||
- **零停机**:Nginx始终指向活跃实例,切换时无中断
|
||||
- **快速回滚**:备份机制允许快速恢复
|
||||
|
||||
---
|
||||
|
||||
## 部署前准备
|
||||
|
||||
### 1. 目录结构创建
|
||||
|
||||
确保以下目录结构存在:
|
||||
|
||||
```
|
||||
D:\EPproject\LabelReplaceServer\
|
||||
├── deployment/
|
||||
│ ├── blue/ # 蓝实例应用目录
|
||||
│ ├── green/ # 绿实例应用目录
|
||||
│ ├── backups/ # 备份目录
|
||||
│ ├── logs/ # 部署日志目录
|
||||
│ ├── scripts/ # 部署脚本目录
|
||||
│ │ ├── build-and-publish.ps1
|
||||
│ │ ├── health-check.ps1
|
||||
│ │ ├── deploy-blue-green.ps1
|
||||
│ │ ├── stop-instance.ps1
|
||||
│ │ └── rollback.ps1
|
||||
│ └── config/
|
||||
│ └── deployment-config.json
|
||||
├── src/
|
||||
├── publish/
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 2. 创建必要的目录
|
||||
|
||||
```powershell
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\blue
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\green
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\backups
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\logs
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\scripts
|
||||
mkdir D:\EPproject\LabelReplaceServer\deployment\config
|
||||
```
|
||||
|
||||
### 3. 配置Nginx反向代理
|
||||
|
||||
在你的Nginx配置文件中(通常是 `nginx.conf`),按照以下方式配置:
|
||||
|
||||
```nginx
|
||||
upstream backend {
|
||||
# 蓝绿实例,一个为主,一个为备用
|
||||
server 127.0.0.1:5000 max_fails=2 fail_timeout=10s;
|
||||
server 127.0.0.1:5001 backup;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 重要:设置连接超时
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location /api/health {
|
||||
proxy_pass http://backend;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键配置说明**:
|
||||
- `max_fails=2`:在2次失败后标记服务器为down
|
||||
- `fail_timeout=10s`:故障超时10秒
|
||||
- `backup`:指定备用服务器,平时不接收流量
|
||||
|
||||
---
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 第一次初始化部署
|
||||
|
||||
**步骤1**:手动启动蓝实例
|
||||
|
||||
```powershell
|
||||
# 在PowerShell中执行以下命令
|
||||
|
||||
# 编译发布到blue目录
|
||||
D:\EPproject\LabelReplaceServer\deployment\scripts\build-and-publish.ps1 `
|
||||
-OutputDirectory "D:\EPproject\LabelReplaceServer\deployment\blue" `
|
||||
-Version "1.0.0"
|
||||
|
||||
# 手动启动蓝实例
|
||||
cd D:\EPproject\LabelReplaceServer\deployment\blue
|
||||
$env:DEPLOYMENT_INSTANCE = "blue"
|
||||
$env:SHUTDOWN_TIMEOUT = "30"
|
||||
.\CONTROLLER.exe
|
||||
```
|
||||
|
||||
**步骤2**:验证蓝实例运行
|
||||
|
||||
```powershell
|
||||
# 在另一个PowerShell终端中
|
||||
curl http://localhost:5000/api/health
|
||||
|
||||
# 应该返回:
|
||||
# {
|
||||
# "status": "healthy",
|
||||
# "instance": "blue",
|
||||
# "port": 5000,
|
||||
# ...
|
||||
# }
|
||||
```
|
||||
|
||||
**步骤3**:初始化部署状态
|
||||
|
||||
```powershell
|
||||
# 创建初始状态文件
|
||||
$state = @{
|
||||
activeInstance = "blue"
|
||||
lastUpdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
version = "1.0.0"
|
||||
}
|
||||
|
||||
$state | ConvertTo-Json |
|
||||
Set-Content -Path "D:\EPproject\LabelReplaceServer\deployment\instance_state.json" -Force
|
||||
```
|
||||
|
||||
**步骤4**:更新Nginx配置
|
||||
|
||||
修改Nginx配置,让主服务器指向蓝实例(5000),备用指向绿实例(5001)。
|
||||
|
||||
### 后续部署流程(核心部署脚本)
|
||||
|
||||
一旦初始化完成,所有后续部署都通过以下命令执行:
|
||||
|
||||
```powershell
|
||||
# 执行蓝绿部署(自动选择非活跃实例)
|
||||
D:\EPproject\LabelReplaceServer\deployment\scripts\deploy-blue-green.ps1 `
|
||||
-Version "1.1.0"
|
||||
|
||||
# 或指定目标实例
|
||||
D:\EPproject\LabelReplaceServer\deployment\scripts\deploy-blue-green.ps1 `
|
||||
-Version "1.1.0" `
|
||||
-TargetInstance "green"
|
||||
```
|
||||
|
||||
**部署脚本执行流程**:
|
||||
|
||||
```
|
||||
1. 确定当前活跃实例(读取 instance_state.json)
|
||||
├─ 若为 blue → 部署到 green
|
||||
├─ 若为 green → 部署到 blue
|
||||
|
||||
2. 编译新版本到非活跃实例
|
||||
├─ 执行 dotnet clean/restore/build/publish
|
||||
├─ 保存当前版本为备份
|
||||
|
||||
3. 启动新实例
|
||||
├─ 设置环境变量 DEPLOYMENT_INSTANCE=green/blue
|
||||
├─ 启动 CONTROLLER.exe
|
||||
|
||||
4. 健康检查(最多30次重试,每次间隔1秒)
|
||||
├─ 调用 /api/health 端点
|
||||
├─ 若成功 → 继续
|
||||
├─ 若失败 → 回滚并退出
|
||||
|
||||
5. 切换流量(更新Nginx配置或DNS)
|
||||
├─ 更新 instance_state.json
|
||||
├─ Nginx自动切换到新实例
|
||||
|
||||
6. 优雅关闭旧实例
|
||||
├─ 等待旧实例完成当前请求(最多30秒)
|
||||
├─ 停止旧实例进程
|
||||
|
||||
7. 记录日志
|
||||
├─ 保存到 deployment/logs/deployment.log
|
||||
```
|
||||
|
||||
**部署中发生了什么?**
|
||||
|
||||
| 时间 | 操作 | 客户端体验 |
|
||||
|------|------|---------|
|
||||
| T=0s | 新实例启动中 | 请求转发到蓝/绿 ✓ |
|
||||
| T=2s | 健康检查中 | 请求转发到蓝/绿 ✓ |
|
||||
| T=5s | 状态更新 | 可能短暂延迟(<1s) |
|
||||
| T=7s | 旧实例关闭 | 新请求转发到新实例 ✓ |
|
||||
|
||||
---
|
||||
|
||||
## 环境变量
|
||||
|
||||
### 部署实例标识
|
||||
|
||||
启动应用时,需要设置环境变量标识实例:
|
||||
|
||||
```powershell
|
||||
# 蓝实例
|
||||
$env:DEPLOYMENT_INSTANCE = "blue"
|
||||
$env:SHUTDOWN_TIMEOUT = "30"
|
||||
.\CONTROLLER.exe
|
||||
|
||||
# 或
|
||||
|
||||
# 绿实例
|
||||
$env:DEPLOYMENT_INSTANCE = "green"
|
||||
$env:SHUTDOWN_TIMEOUT = "30"
|
||||
.\CONTROLLER.exe
|
||||
```
|
||||
|
||||
### 环境变量说明
|
||||
|
||||
| 变量名 | 说明 | 默认值 | 用途 |
|
||||
|--------|------|--------|------|
|
||||
| `DEPLOYMENT_INSTANCE` | 实例标识 | "blue" | 决定使用的端口(blue=5000, green=5001) |
|
||||
| `SHUTDOWN_TIMEOUT` | 优雅关闭超时 | "30" | 秒数,等待现有请求完成的最长时间 |
|
||||
| `ASPNETCORE_ENVIRONMENT` | 环境 | "Production" | ASP.NET Core 环境配置 |
|
||||
|
||||
---
|
||||
|
||||
## 健康检查端点
|
||||
|
||||
### `/api/health` 端点
|
||||
|
||||
**请求**:
|
||||
```
|
||||
GET /api/health
|
||||
```
|
||||
|
||||
**响应 (200 OK)**:
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"instance": "blue",
|
||||
"port": 5000,
|
||||
"timestamp": "2026-05-15T10:30:45Z",
|
||||
"uptime": "2026-05-15T10:15:30Z",
|
||||
"environment": "Production"
|
||||
}
|
||||
```
|
||||
|
||||
### `/api/version` 端点
|
||||
|
||||
**请求**:
|
||||
```
|
||||
GET /api/version
|
||||
```
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"instance": "blue",
|
||||
"port": 5000,
|
||||
"buildTime": "2026-05-15T10:15:30Z",
|
||||
"timestamp": "2026-05-15T10:30:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 回滚流程
|
||||
|
||||
### 发生故障时快速回滚
|
||||
|
||||
```powershell
|
||||
# 执行回滚脚本
|
||||
D:\EPproject\LabelReplaceServer\deployment\scripts\rollback.ps1
|
||||
```
|
||||
|
||||
**回滚流程**:
|
||||
|
||||
```
|
||||
1. 读取当前活跃实例
|
||||
2. 停止当前实例
|
||||
3. 从最新备份恢复文件
|
||||
4. 启动恢复的实例
|
||||
5. 健康检查验证
|
||||
6. 更新状态文件
|
||||
7. Nginx自动切换回旧端口
|
||||
```
|
||||
|
||||
**预期结果**:
|
||||
|
||||
```
|
||||
前状态:green (新版本) 活跃
|
||||
回滚后:blue (旧版本) 活跃
|
||||
|
||||
客户端流量自动转向 blue(端口 5000)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 监控和日志
|
||||
|
||||
### 日志位置
|
||||
|
||||
所有部署日志记录在:
|
||||
|
||||
```
|
||||
D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log
|
||||
```
|
||||
|
||||
### 日志内容示例
|
||||
|
||||
```
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] ========================================
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] 蓝绿部署流程开始
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] 版本: 1.1.0
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] 已加载部署配置
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] 当前活跃实例: blue
|
||||
[2026-05-15 10:30:45] [INFO] [BluGreen] 下一个部署实例: green
|
||||
[2026-05-15 10:35:12] [INFO] [BluGreen] 健康检查通过
|
||||
[2026-05-15 10:35:13] [INFO] [BluGreen] 已更新活跃实例为: green (版本: 1.1.0)
|
||||
[2026-05-15 10:35:15] [INFO] [BluGreen] 蓝绿部署完成!
|
||||
```
|
||||
|
||||
### 实例状态文件
|
||||
|
||||
```
|
||||
D:\EPproject\LabelReplaceServer\deployment\instance_state.json
|
||||
```
|
||||
|
||||
**内容示例**:
|
||||
```json
|
||||
{
|
||||
"activeInstance": "green",
|
||||
"lastUpdate": "2026-05-15 10:35:15",
|
||||
"version": "1.1.0"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题1:新实例健康检查失败
|
||||
|
||||
**症状**:部署中止,显示"新实例健康检查失败"
|
||||
|
||||
**排查步骤**:
|
||||
```powershell
|
||||
# 1. 检查应用是否启动
|
||||
Get-Process CONTROLLER
|
||||
|
||||
# 2. 手动测试健康检查
|
||||
curl http://localhost:5000/api/health
|
||||
curl http://localhost:5001/api/health
|
||||
|
||||
# 3. 查看部署日志
|
||||
Get-Content "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log" -Tail 50
|
||||
|
||||
# 4. 检查应用日志
|
||||
Get-Content "D:\EPproject\LabelReplaceServer\deployment\logs\api_log-*.txt" -Tail 50
|
||||
```
|
||||
|
||||
### 问题2:旧实例无法停止
|
||||
|
||||
**症状**:部署完成但旧实例仍在运行
|
||||
|
||||
**解决方案**:
|
||||
```powershell
|
||||
# 强制停止所有 CONTROLLER 进程
|
||||
Get-Process CONTROLLER | Stop-Process -Force
|
||||
|
||||
# 等待2秒后验证
|
||||
Start-Sleep -Seconds 2
|
||||
Get-Process CONTROLLER -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
### 问题3:Nginx未切换流量
|
||||
|
||||
**症状**:切换后客户端仍连接到旧实例
|
||||
|
||||
**排查步骤**:
|
||||
```
|
||||
1. 确认 instance_state.json 已更新
|
||||
- 检查 activeInstance 字段是否变更
|
||||
|
||||
2. 检查 Nginx 配置
|
||||
- 确保上游地址正确
|
||||
- 重新加载 Nginx: nginx -s reload
|
||||
|
||||
3. 清除DNS缓存(如适用)
|
||||
- ipconfig /flushdns
|
||||
|
||||
4. 检查客户端连接
|
||||
- 新连接应转向新实例
|
||||
- 已建立连接可能保持不变
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. **选择合适的部署时间**
|
||||
- 避免业务高峰期
|
||||
- 选择流量较少的时间窗口
|
||||
- 建议凌晨或夜间部署
|
||||
|
||||
### 2. **监控部署过程**
|
||||
- 打开日志文件实时查看
|
||||
- 监控两个端口的流量
|
||||
- 部署后进行功能验证
|
||||
|
||||
### 3. **备份管理**
|
||||
- 定期清理旧备份(保留最近5个版本)
|
||||
- 备份目录空间充足
|
||||
- 测试备份可恢复性
|
||||
|
||||
### 4. **健康检查优化**
|
||||
```powershell
|
||||
# 手动测试健康检查响应时间
|
||||
Measure-Command {
|
||||
curl http://localhost:5000/api/health
|
||||
}
|
||||
```
|
||||
|
||||
### 5. **客户端重连机制**
|
||||
- 建议客户端实现自动重连
|
||||
- 设置合理的重试次数(3-5次)
|
||||
- 指数退避策略
|
||||
|
||||
---
|
||||
|
||||
## 快速参考命令
|
||||
|
||||
```powershell
|
||||
# 查看当前活跃实例
|
||||
Get-Content "D:\EPproject\LabelReplaceServer\deployment\instance_state.json" | ConvertFrom-Json
|
||||
|
||||
# 查看部署日志(最近50行)
|
||||
Get-Content "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log" -Tail 50
|
||||
|
||||
# 测试蓝实例
|
||||
curl http://localhost:5000/api/health
|
||||
|
||||
# 测试绿实例
|
||||
curl http://localhost:5001/api/health
|
||||
|
||||
# 查看CONTROLLER进程
|
||||
Get-Process CONTROLLER
|
||||
|
||||
# 部署新版本
|
||||
& "D:\EPproject\LabelReplaceServer\deployment\scripts\deploy-blue-green.ps1" -Version "1.2.0"
|
||||
|
||||
# 回滚到上一个版本
|
||||
& "D:\EPproject\LabelReplaceServer\deployment\scripts\rollback.ps1"
|
||||
|
||||
# 停止应用
|
||||
Get-Process CONTROLLER | Stop-Process -Force
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题 (FAQ)
|
||||
|
||||
**Q: 为什么要用固定端口而不是动态端口?**
|
||||
A: 固定端口更简单且不需要Nginx权限更改,部署脚本也更简洁。Nginx配置一次后无需修改。
|
||||
|
||||
**Q: 部署期间客户端会断线吗?**
|
||||
A: 新连接会自动转向新实例。已建立的长连接会保持到旧实例,直到超时或主动关闭。
|
||||
|
||||
**Q: 回滚需要多长时间?**
|
||||
A: 通常2-5分钟,取决于实例启动时间和健康检查通过速度。
|
||||
|
||||
**Q: 可以同时运行两个实例吗?**
|
||||
A: 可以,但同一时间只有一个实例作为"活跃实例"接收流量。另一个是备用。
|
||||
|
||||
**Q: 如何验证部署成功?**
|
||||
A:
|
||||
1. 检查 instance_state.json,确认 activeInstance 已变更
|
||||
2. 调用 /api/version 确认返回新版本号
|
||||
3. 检查部署日志最后一行应显示"蓝绿部署完成"
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
这个固定端口蓝绿部署方案提供了:
|
||||
- ✅ **零停机部署**:业务连续性有保障
|
||||
- ✅ **快速回滚**:问题发生时可秒级回滚
|
||||
- ✅ **简单配置**:固定端口,Nginx配置一次即可
|
||||
- ✅ **自动化**:PowerShell脚本全程自动化
|
||||
- ✅ **完整日志**:所有操作都有详细日志记录
|
||||
|
||||
祝你部署顺利!🚀
|
||||
Reference in New Issue
Block a user