# 固定端口蓝绿部署完整指南 ## 架构概述 本方案采用**固定端口蓝绿部署**策略,允许在不中断客户端访问的情况下更新应用程序: ``` 网络流量 (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脚本全程自动化 - ✅ **完整日志**:所有操作都有详细日志记录 祝你部署顺利!🚀