AB 压测的坑,请求被 ThrottleRequests 拦截
今天用AB压测单核1G的机器,-c 在10以上就挂掉了,Failed requests 比重贼高
ab -c 20 -t 10 -k -T "application/json" -H "Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvd3d3LnpoemhlLmNvbSIsImlhdCI6MTU2MzE4MjA1OCwiZXhwIjoxNTY2MzM1NjU5LCJuYmYiOjE1NjMxODIwNTksImp0aSI6IlRiYXR5amhpMGJ6eHRNeEciLCJzdWIiOjEsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.PV-S7b_fbSPgtAk-6r-cDqGkoFL-UOsGJWVfQUV6p5E" http://ys.test/api/articles
经检查,发现框架抛出429异常导致请求失败,异常由ThrottleRequests 中间件抛出
查看 app/Http/kernel.php
其中
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
\Barryvdh\Cors\HandleCors::class,
'throttle:60,1',
'bindings',
],
];
api 引用了 'throttle:60,1' ,就是这个玩意,注释掉从新压测 , ok了!
这里是 ThrottleRequests的handle源码
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
$key = $this->resolveRequestSignature($request);
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
throw $this->buildException($key, $maxAttempts);
}
$this->limiter->hit($key, $decayMinutes);
$response = $next($request);
return $this->addHeaders(
$response, $maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts)
);
}
ThrottleRequests中间件中 60和1
的意思是一分钟限制60次。 把客户端请求的请求源ip啥的,加密成1个key(代表一个独立的请求对象),存储在缓存中, 如果一分钟内超过这个限制,那么服务器就抛出 429: Too Many Attempts.
并且在头部回传两个个响应头: X-RateLimit-Limit(限制次数), X-RateLimit-Remaining(剩下多少次),如下图所示
请求超过限制,会返回 Retry-After(多少秒后恢复正常),针对不同的应用设置一个符合自己应用的参数
推荐文章: