2022-07-09

PowerShell で大量の HTTP リクエストを送る場合の Tips

大量のアクセスログがほしい事情で、テスト環境に大量のリクエストを送りつける必要があった。

JMeter とか Gatling 使えば済む話なのだけど、すぐに使い回せるものがなかったし、パパっとやってしまいたかったので PowerShell を使ってみたら、エラーになった。

$requests = 'aaa=10&bbb=20', 'aaa=11&bbb=21', 'aaa=12&bbb=22'
$requests * 100000 | ForEach-Object -Parallel {
Invoke-WebRequest -Method Get -Uri "https://$using:testDomaain?$_"
$jitter = Get-Random -Minimum 3 -Maximum 23
Start-Sleep -Milliseconds (95 + $jitter) # 待ち
} -ThrottleLimit 100 | ConvertTo-Json | Set-Content ./responses.json

こういうのでタコ殴りにすると...

Only one usage of each socket address (protocol/network address/port) is normally permitted

15000 件を超えた辺りでこうなった。なんだ?ググる。

ポートが枯渇するんだと。 PowerShell の実装を見た訳じゃないけど、 大量に実行された Invoke-WebRequestHttpClient を大量作成したのであろうことは、想像するに易い。

同じ HttpClient を使い回せば良いらしいので、そうした。

$requests = 'aaa=10&bbb=20', 'aaa=11&bbb=21', 'aaa=12&bbb=22'
$h = New-Object System.Net.Http.HttpClient
$requests * 100000 | ForEach-Object -Parallel {
($using:h).GetAsync("https://$using:testDomaain?$_").GetAwaiter()
$jitter = Get-Random -Minimum 3 -Maximum 23
Start-Sleep -Milliseconds (95 + $jitter) # 待ち
} -ThrottleLimit 100 | ForEach-Object {$_.GetResult()} | ConvertTo-Json | Set-Content ./responses.json

そんだけ。