# CE-005: 并发登录压测 & 速率限制验证 # 验证:高并发下速率限制(Rate Limiting)是否正常工作 param( [string]$BaseURL = "http://localhost:8080", [int]$Concurrency = 20, [int]$Duration = 15, [switch]$Verbose ) $ErrorActionPreference = "Continue" Write-Host "=== CE-005: 并发登录压测 & 速率限制验证 ===" -ForegroundColor Magenta Write-Host "目标服务: $BaseURL" Write-Host "并发协程: $Concurrency" Write-Host "持续时间: ${Duration}s" Write-Host "" # 前置检查 Write-Host "[前置检查] 服务健康状态..." -ForegroundColor Cyan try { $health = Invoke-RestMethod -Uri "$BaseURL/health/ready" -TimeoutSec 5 if ($health.status -ne "UP") { Write-Host "❌ 服务不健康,终止实验" -ForegroundColor Red exit 1 } Write-Host " ✅ 服务状态: UP" -ForegroundColor Green } catch { Write-Host " ❌ 无法连接到服务: $($_.Exception.Message)" -ForegroundColor Red exit 1 } # 并发压测 Write-Host "`n[压测中] 启动 $Concurrency 个并发协程,持续 ${Duration}s..." -ForegroundColor Cyan $startTime = Get-Date $jobs = 1..$Concurrency | ForEach-Object { $workerID = $_ Start-Job -ScriptBlock { param($BaseURL, $Duration, $workerID) $end = (Get-Date).AddSeconds($Duration) $results = @{ total = 0 http_200 = 0 http_400 = 0 http_401 = 0 http_429 = 0 http_500 = 0 other = 0 errors = 0 } while ((Get-Date) -lt $end) { try { $body = @{ account = "chaos_test_user_$workerID" password = "wrong_password_chaos_test" } | ConvertTo-Json $resp = Invoke-WebRequest ` -Uri "$BaseURL/api/v1/auth/login" ` -Method POST ` -Body $body ` -ContentType "application/json" ` -ErrorAction SilentlyContinue ` -TimeoutSec 5 $results.total++ switch ($resp.StatusCode) { 200 { $results.http_200++ } 400 { $results.http_400++ } 401 { $results.http_401++ } 429 { $results.http_429++ } 500 { $results.http_500++ } default { $results.other++ } } } catch { $results.total++ $results.errors++ } Start-Sleep -Milliseconds 50 } return $results } -ArgumentList $BaseURL, $Duration, $workerID } Write-Host " ⏳ 等待实验完成..." -ForegroundColor Yellow $jobs | Wait-Job | Out-Null $elapsed = (Get-Date) - $startTime Write-Host " ✅ 实验完成,耗时: $([math]::Round($elapsed.TotalSeconds, 1))s" -ForegroundColor Green # 汇总结果 $totals = @{ total = 0; http_200 = 0; http_400 = 0; http_401 = 0 http_429 = 0; http_500 = 0; other = 0; errors = 0 } $jobs | Receive-Job | ForEach-Object { $r = $_ $totals.total += $r.total $totals.http_200 += $r.http_200 $totals.http_400 += $r.http_400 $totals.http_401 += $r.http_401 $totals.http_429 += $r.http_429 $totals.http_500 += $r.http_500 $totals.other += $r.other $totals.errors += $r.errors } $jobs | Remove-Job # 显示结果 $rateTotal = [math]::Max($totals.total, 1) Write-Host "`n=== 压测结果 ===" -ForegroundColor Magenta Write-Host "总请求数: $($totals.total)" Write-Host "吞吐量: $([math]::Round($totals.total / $elapsed.TotalSeconds, 1)) req/s" Write-Host "" Write-Host "HTTP 响应分布:" Write-Host " 200 成功: $($totals.http_200) ($([math]::Round($totals.http_200 / $rateTotal * 100, 1))%)" Write-Host " 400 请求错误: $($totals.http_400) ($([math]::Round($totals.http_400 / $rateTotal * 100, 1))%)" Write-Host " 401 认证失败: $($totals.http_401) ($([math]::Round($totals.http_401 / $rateTotal * 100, 1))%)" Write-Host " 429 速率限制: $($totals.http_429) ($([math]::Round($totals.http_429 / $rateTotal * 100, 1))%)" -ForegroundColor Yellow Write-Host " 500 服务错误: $($totals.http_500) ($([math]::Round($totals.http_500 / $rateTotal * 100, 1))%)" -ForegroundColor $(if ($totals.http_500 -gt 0) {"Red"} else {"White"}) Write-Host " 其他/错误: $($totals.other + $totals.errors)" # 验证 Write-Host "`n=== 验证 ===" -ForegroundColor Cyan $passed = 0; $failed = 0 # 验证1:速率限制触发 if ($totals.http_429 -gt 0) { Write-Host " ✅ 速率限制已触发 ($($totals.http_429) 次 429 响应)" -ForegroundColor Green $passed++ } else { Write-Host " ❌ 速率限制未触发(0 次 429),请检查 config.yaml ratelimit 配置" -ForegroundColor Red $failed++ } # 验证2:无服务器错误(500 不应出现) if ($totals.http_500 -eq 0) { Write-Host " ✅ 无 5xx 错误,服务稳定" -ForegroundColor Green $passed++ } else { Write-Host " ❌ 出现 $($totals.http_500) 次 5xx 错误,存在系统稳定性问题" -ForegroundColor Red $failed++ } # 验证3:QPS 合理(服务未被压垮) $targetQPS = $Concurrency * 5 # 理论最大 QPS $actualQPS = $totals.total / $elapsed.TotalSeconds if ($actualQPS -gt 0) { Write-Host " ✅ 服务保持响应,实际 QPS: $([math]::Round($actualQPS, 1))" -ForegroundColor Green $passed++ } else { Write-Host " ❌ 服务可能已无响应" -ForegroundColor Red $failed++ } Write-Host "`n=== 实验总结 ===" -ForegroundColor Magenta Write-Host "通过: $passed 失败: $failed" if ($failed -eq 0) { Write-Host "`n✅ CE-005 通过 — 速率限制在高并发下正常工作" -ForegroundColor Green exit 0 } else { Write-Host "`n❌ CE-005 失败 — 存在 $failed 个验证问题" -ForegroundColor Red exit 1 }