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

AB压测失败,请求被 ThrottleRequests 拦截

经检查,发现框架抛出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(剩下多少次),如下图所示

AB压测失败,请求被 ThrottleRequests 拦截

请求超过限制,会返回 Retry-After(多少秒后恢复正常),针对不同的应用设置一个符合自己应用的参数

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

请教一下,压测通常是内网压测还是外网压测呢?

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!