param( [string]$Version = (Get-Date -Format "yyyyMMdd-HHmmss"), [string]$TargetInstance = "auto" ) $ErrorActionPreference = "Stop" $configPath = "D:\EPproject\LabelReplaceServer\deployment\config\deployment-config.json" $stateFile = "D:\EPproject\LabelReplaceServer\deployment\instance_state.json" $logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log" function Log { param([string]$Message, [string]$Level = "INFO") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logEntry = "[$timestamp] [$Level] [BluGreen] $Message" Write-Host $logEntry -ForegroundColor $(switch($Level) { "ERROR" { "Red" } "WARN" { "Yellow" } "INFO" { "Green" } "DEBUG" { "Gray" } default { "White" } }) $logDirPath = Split-Path -Parent $logFile if (!(Test-Path $logDirPath)) { New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null } Add-Content -Path $logFile -Value $logEntry } function GetCurrentActiveInstance { if (Test-Path $stateFile) { try { $state = Get-Content $stateFile | ConvertFrom-Json return $state.activeInstance } catch { Log "读取状态文件失败,假设Blue为活跃实例" "WARN" return "blue" } } return "blue" } function SetActiveInstance { param([string]$Instance) $state = @{ activeInstance = $Instance lastUpdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" version = $Version } $logDirPath = Split-Path -Parent $stateFile if (!(Test-Path $logDirPath)) { New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null } $state | ConvertTo-Json | Set-Content -Path $stateFile -Force Log "已更新活跃实例为: $Instance (版本: $Version)" "INFO" } function StopInstance { param([string]$Instance, [int]$Port) Log "尝试停止 $Instance 实例 (端口: $Port)..." "INFO" try { $processes = Get-Process | Where-Object { $_.ProcessName -eq "CONTROLLER" -and $_.Handles -gt 0 } foreach ($proc in $processes) { try { $proc | Stop-Process -Force -ErrorAction Stop Log "已停止进程 $($proc.Id)" "INFO" } catch { Log "停止进程失败: $_" "WARN" } } Start-Sleep -Seconds 2 $stillRunning = Get-Process | Where-Object { $_.ProcessName -eq "CONTROLLER" } if ($stillRunning) { Log "警告: 仍有 CONTROLLER 进程运行" "WARN" return $false } Log "$Instance 实例已成功停止" "INFO" return $true } catch { Log "停止 $Instance 实例失败: $_" "ERROR" return $false } } function StartInstance { param([string]$Instance, [string]$Directory, [string]$Port, [string]$Environment) Log "启动 $Instance 实例 (端口: $Port, 目录: $Directory)..." "INFO" try { if (!(Test-Path $Directory)) { throw "目录不存在: $Directory" } $exePath = Join-Path $Directory "CONTROLLER.exe" if (!(Test-Path $exePath)) { throw "可执行文件不存在: $exePath" } $env:DEPLOYMENT_INSTANCE = if ($Instance -eq "green") { "green" } else { "blue" } $env:SHUTDOWN_TIMEOUT = "30" $process = Start-Process -FilePath $exePath -WorkingDirectory $Directory -PassThru -ErrorAction Stop Log "$Instance 实例已启动 (PID: $($process.Id))" "INFO" Start-Sleep -Seconds 2 return $process.Id } catch { Log "启动 $Instance 实例失败: $_" "ERROR" throw } } try { Log "========================================" "INFO" Log "蓝绿部署流程开始" "INFO" Log "版本: $Version" "INFO" Log "========================================" "INFO" if (!(Test-Path $configPath)) { throw "配置文件不存在: $configPath" } $config = Get-Content $configPath | ConvertFrom-Json Log "已加载部署配置" "INFO" $currentActive = GetCurrentActiveInstance Log "当前活跃实例: $currentActive" "INFO" $nextInstance = if ($currentActive -eq "blue") { "green" } else { "blue" } if ($TargetInstance -ne "auto") { $nextInstance = $TargetInstance Log "使用指定的目标实例: $nextInstance" "INFO" } Log "下一个部署实例: $nextInstance" "INFO" $targetConfig = if ($nextInstance -eq "green") { $config.GreenInstance } else { $config.BlueInstance } Log "========== 第一步:编译和发布 ==========" "INFO" $publishScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\build-and-publish.ps1" $buildResult = & $publishScript -OutputDirectory $targetConfig.Directory -Version $Version -Configuration Release if (!$buildResult) { throw "编译和发布失败" } Log "========== 第二步:启动新实例 ==========" "INFO" $newPid = StartInstance -Instance $nextInstance -Directory $targetConfig.Directory ` -Port $targetConfig.Port -Environment $targetConfig.Environment Log "========== 第三步:健康检查 ==========" "INFO" $healthScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\health-check.ps1" $healthResult = & $healthScript -Instance $nextInstance -Port $targetConfig.Port if (!$healthResult) { throw "新实例健康检查失败,中止部署" } Log "========== 第四步:切换流量 ==========" "INFO" SetActiveInstance -Instance $nextInstance Log "========== 第五步:停止旧实例 ==========" "INFO" $oldConfig = if ($currentActive -eq "green") { $config.GreenInstance } else { $config.BlueInstance } Log "等待旧实例优雅关闭 (超时: $($config.Deployment.GracefulShutdownTimeout) 秒)..." "INFO" Start-Sleep -Seconds 5 StopInstance -Instance $currentActive -Port $oldConfig.Port Log "========================================" "INFO" Log "蓝绿部署完成!" "INFO" Log "新活跃实例: $nextInstance (端口: $($targetConfig.Port))" "INFO" Log "========================================" "INFO" } catch { Log "蓝绿部署失败: $_" "ERROR" Log "错误详情: $($_.Exception.StackTrace)" "ERROR" exit 1 }