laravel百万级qps限流需科学设定阈值,先验证throttle中间件生效、缓存驱动为redis,再通过wrk压测反推基准值并预留15%冗余,最后按身份/接口/熔断分层限流且隔离限流专用redis实例。

在百万级QPS压测场景下,Laravel限流阈值若凭经验拍脑袋设定,轻则导致大量429响应误伤真实用户,重则因计数器争抢加剧Redis压力反成性能瓶颈。
先确认当前限流生效路径是否走通
执行 php artisan route:list --middleware=throttle,检查目标API路由是否确实挂载了 throttle 中间件。没挂载的路由再调高阈值也无效。
用 curl 模拟单IP高频请求:for i in {1..65}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost/api/test; done,观察是否在第61次返回 429。不返回说明缓存驱动未生效或中间件未加载。
【关键前提】必须确保 config/cache.php 中 'default' 驱动为 redis 或 memcached,file 驱动在高并发下会因文件锁直接崩溃。
按压测结果反推每分钟阈值基准值
第一步:用 wrk 压测工具发起 30 秒持续压测:wrk -t4 -c200 -d30s http://your-api.com/api/data,记录实际达成 QPS 和失败率。
第二步:将压测QPS × 60 得到理论每分钟请求数,例如实测稳定峰值为 12000 QPS → 基准阈值设为 720000/minute。这数字不能直接填进 throttle 参数——Redis 计数器本身有毫秒级延迟,需预留 15% 冗余。
第三步:在 Kernel.php 的 throttle:api 中临时改为 throttle:720000,1,再次压测。若失败率仍高于 0.5%,说明 Redis 连接池或网络延迟成为新瓶颈,需跳转到「优化计数器底层」环节。
区分流量类型设置多层限流策略
方法一:按用户身份分层(推荐用于含登录态的API)
在 app/Providers/AppServiceProvider.php 的 boot() 中注册:
RateLimiter::for('user_api', function (Request $request) {<br> return $request->user()<br> ? Limit::perMinute(10000)->by($request->user()->id)<br> : Limit::perMinute(200)->by($request->ip());<br>});
注意:未登录用户若共用 IP 限流,需防代理池穿透——此时应改用 $request->header('X-Real-IP') 并校验 Nginx 转发头可信性。
方法二:按接口敏感度分级
支付类接口加严:Route::post('/pay', [PayController::class, 'handle'])->middleware('throttle:10,1');
资讯类接口放宽:Route::get('/news', [NewsController::class, 'index'])->middleware('throttle:5000,1');
方法三:动态熔断兜底(应对突发流量)
在 config/cache.php 中启用 Redis 的 lazy_write 模式,避免计数器写入阻塞主流程;同时配置 'store' => 'redis' 下的 'connection' => 'limiting',将限流专用连接池与业务Redis物理隔离。
优化计数器底层性能
修改 config/database.php,在 redis 配置块内增加:
'limiting' => [<br> 'url' => env('REDIS_LIMITING_URL'),<br> 'host' => env('REDIS_LIMITING_HOST', '127.0.0.1'),<br> 'password' => env('REDIS_LIMITING_PASSWORD', null),<br> 'port' => env('REDIS_LIMITING_PORT', 6380),<br> 'database' => 2,<br>],
然后在 .env 中新增 REDIS_LIMITING_PORT=6380,指向一台专用于限流计数的 Redis 实例。这能避免业务缓存与限流计数器争抢同一 Redis 连接带宽。
执行 php artisan config:cache 生效配置后,重启 PHP-FPM 进程。











