Files
user-system/scripts/chaos/ce-005-concurrent-login.ps1
long-agent 5b6bd93179 refactor: 整理项目根目录结构
整理内容:
- 删除 60+ 临时测试输出文件 (*.txt)
- 移动二进制文件到 bin/ 目录
- 移动 Shell 脚本到 scripts/ 目录
  - scripts/dev/: check_gitea.sh, check_sub2api.sh, run_tests.sh
  - scripts/deploy/: deploy_*.sh, simple_deploy.sh
  - scripts/ops/: fix_nginx.sh, fix_ssl.sh, install_docker.sh
  - scripts/test/: test_*.sh, test_*.bat
- 移动批处理文件到 scripts/
- 移动 Python 脚本到 tools/
- 清理临时日志文件

保留根目录必要文件:
- go.mod, go.sum, go.work
- Makefile, docker-compose.yml
- .env.example, .gitignore
- README.md, AGENTS.md, DEPLOY_GUIDE.md

验证: go build ./... && go test ./... 通过
2026-04-07 18:10:36 +08:00

173 lines
5.9 KiB
PowerShell
Raw 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.
# 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++
}
# 验证3QPS 合理(服务未被压垮)
$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
}