# .NET Core 无停机部署解决方案计划 ## 问题描述 当前后端程序(CONTROLLER.exe)在需要更新时,需要关闭EXE程序再启动,这导致在更新期间客户端无法访问服务。 ## 解决方案概述 实现一个无停机部署(Zero Downtime Deployment)系统,通过以下关键组件: 1. **蓝绿部署**:同时运行两个版本的应用程序 2. **反向代理**:使用IIS或Nginx进行流量转发 3. **健康检查**:确保只有健康的实例才接收流量 4. **优雅关闭**:确保正在处理的请求完成后再关闭应用 ## 实现步骤 ### 第一阶段:部署基础设施准备 #### 1.1 创建部署目录结构 ``` D:\EPproject\LabelReplaceServer\ ├── deployment/ │ ├── blue/ (蓝实例目录) │ ├── green/ (绿实例目录) │ ├── scripts/ (部署脚本) │ └── config/ (配置文件) ├── src/ (源代码) ├── publish/ (发布包) └── docs/ ``` #### 1.2 配置应用程序级别 - **创建端口配置文件**:允许蓝绿实例使用不同端口(如5000和5001) - **修改Program.cs**:支持从环境变量读取端口号 - **创建健康检查端点**:GET `/health` 返回应用健康状态 #### 1.3 配置反向代理 - **选择反向代理方案**: - 选项A:使用IIS Application Request Routing (ARR) - 选项B:使用Nginx - 选项C:使用.NET Reverse Proxy(YARP库) - **配置流量路由规则** - **设置故障转移策略** ### 第二阶段:代码修改 #### 2.1 修改Program.cs支持端口配置 - 从环境变量或启动参数读取端口号 - 默认使用5000端口,允许通过参数覆盖 #### 2.2 添加健康检查端点 ```csharp app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.Now })); ``` #### 2.3 添加优雅关闭支持 - 实现ShutdownToken处理 - 等待现有请求完成(超时时间可配置) - 记录关闭事件到日志 #### 2.4 创建版本信息端点 ```csharp app.MapGet("/api/version", () => Results.Ok(new { version = "1.0.0", buildTime = DateTime.Now })); ``` ### 第三阶段:部署脚本创建 #### 3.1 创建PowerShell部署脚本 - **build-and-publish.ps1**:编译并发布应用 - **deploy-blue-green.ps1**:执行蓝绿部署 - **health-check.ps1**:检查实例健康状态 - **switch-traffic.ps1**:切换流量到新实例 - **rollback.ps1**:回滚到上一个版本 #### 3.2 脚本功能详解 **build-and-publish.ps1**: - 编译源代码:`dotnet build -c Release` - 发布应用:`dotnet publish -c Release -o ` - 备份当前版本 **deploy-blue-green.ps1**: - 确定当前活跃实例(蓝或绿) - 将新版本部署到非活跃实例 - 启动新实例并验证健康状态 - 切换反向代理指向新实例 - 停止旧实例(可选保留) **health-check.ps1**: - 调用`/health`端点 - 重试机制(指数退避) - 返回健康状态和时间戳 **switch-traffic.ps1**: - 更新反向代理配置 - 等待现有连接完成 - 优雅关闭旧实例 ### 第四阶段:反向代理配置 #### 4.1 IIS配置(推荐用于Windows) - 配置Application Request Routing (ARR) - 创建服务器农场指向蓝绿实例 - 配置健康探测规则 - 设置故障转移和负载均衡 #### 4.2 Nginx配置(跨平台) ```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; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; } location /health { proxy_pass http://backend; } } ``` #### 4.3 YARP配置(.NET原生) - 在反向代理项目中配置YARP - 定义集群配置(蓝绿实例) - 配置健康检查策略 ### 第五阶段:自动化任务调度 #### 5.1 创建Windows计划任务 - 定期检查新版本可用性 - 自动执行部署流程 - 可选的维护窗口时间设置 #### 5.2 日志和监控 - 记录每次部署信息 - 监控实例健康状态 - 告警机制(可选) ### 第六阶段:测试和验证 #### 6.1 单实例测试 - 测试蓝实例正常运行 - 测试绿实例正常运行 - 测试切换过程 #### 6.2 并发请求测试 - 验证切换期间请求不丢失 - 测试客户端重连机制 - 验证会话保持 #### 6.3 故障场景测试 - 实例启动失败处理 - 健康检查失败处理 - 自动回滚场景 ## 技术选择建议 ### 推荐方案:IIS + PowerShell脚本 + 蓝绿部署 **优点**: - 充分利用Windows环境 - 与.NET原生集成良好 - 已在生产环境中验证 **实现复杂度**:中等 ### 替代方案:Nginx + PowerShell脚本 **优点**: - 更轻量级 - 跨平台支持 - 配置简单 **实现复杂度**:中等 ## 部署流程(执行时) ``` 1. 用户运行: .\deploy-blue-green.ps1 -version "1.2.3" 2. 系统执行: ├─ 编译新版本 ├─ 发布到非活跃实例目录(如./green/) ├─ 启动绿实例(端口5001) ├─ 健康检查直到绿实例就绪 ├─ 更新反向代理配置(转向绿实例) ├─ 等待蓝实例连接优雅完成(30秒超时) ├─ 停止蓝实例 └─ 记录成功日志 3. 客户端体验: - 部署期间服务始终可用 - 可能存在极短时间的连接重置 - 长连接需要实现客户端重连机制 ``` ## 回滚流程 ``` 1. 用户运行: .\rollback.ps1 2. 系统执行: ├─ 检查上一个版本 ├─ 启动上一个版本实例 ├─ 健康检查验证 ├─ 切换反向代理指向 ├─ 停止当前版本 └─ 记录回滚日志 ``` ## 文件清单(需要创建/修改) ### 需要创建的文件: 1. `deployment/scripts/build-and-publish.ps1` - 编译发布脚本 2. `deployment/scripts/deploy-blue-green.ps1` - 部署脚本 3. `deployment/scripts/health-check.ps1` - 健康检查脚本 4. `deployment/scripts/switch-traffic.ps1` - 流量切换脚本 5. `deployment/scripts/rollback.ps1` - 回滚脚本 6. `deployment/scripts/stop-instance.ps1` - 停止实例脚本 7. `deployment/config/app-config.json` - 应用配置模板 8. `deployment/config/iis-config.xml` 或 `nginx.conf` - 反向代理配置 ### 需要修改的文件: 1. `src/CONTROLLER/Program.cs` - 支持端口配置、健康检查、优雅关闭 2. `src/CONTROLLER/appsettings.json` - 添加部署相关配置 ## 预期效果 ✅ **优点**: - 部署时零停机 - 快速回滚能力 - 自动故障检测 - 支持自动化部署 ⚠️ **注意事项**: - 需要额外的服务器资源(运行两个实例) - 需要维护反向代理配置 - 数据库迁移需要特殊处理 - 客户端可能需要实现重连逻辑 ## 实现优先级 1. **必须**:修改Program.cs支持端口配置和健康检查 2. **必须**:创建基础部署脚本 3. **必须**:配置反向代理 4. **应该**:添加优雅关闭支持 5. **可选**:自动化任务调度和监控