Files
LabelChange-server/deployment/scripts/deploy-blue-green.ps1
2026-06-01 16:30:29 +08:00

210 lines
6.5 KiB
PowerShell
Raw Permalink 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.

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
}