laravel请求限流需分层配置、精准设键、驱动可靠:缓存必须用redis/memcached;按场景选key(如设备指纹、租户id、ip+手机号组合);nginx前置漏桶限流;复杂策略用ratelimiter自定义配额并显式指定by()键。

直接上干货:Laravel 请求限流不是加个 throttle 中间件就完事,必须分层配置、精准设键、驱动可靠,否则高并发下形同虚设。
一、基础配置必须确认三件事
很多项目限流失效,根源在起步就错了:
-
缓存驱动必须是 Redis 或 Memcached:不要用
array驱动。多 PHP-FPM 进程下,array缓存各自独立计数,限流完全不生效;生产环境务必检查CACHE_DRIVER=redis并确保 Redis 连通正常。 -
中间件必须已启用:确认
app/Http/Kernel.php的$middlewareGroups['api']中包含\Illuminate\Routing\Middleware\ThrottleRequests::class。 -
路由写法要匹配策略:比如定义了命名限流策略
api-by-user,路由就得写->middleware('throttle:api-by-user'),不能只写throttle:60,1混淆逻辑。
二、按场景选对限流键(key)
默认按 IP 或用户 ID 限流,在真实部署中极易误杀或漏防:
-
走 CDN 或负载均衡时:所有请求共用一个公网 IP,
by=request:ip会让全站用户互相拖累。应改用设备指纹(如X-Device-ID)、API Key、或 JWT 中的jti字段。 -
小程序或 App 场景:用
by($request->header('X-Openid'))或by($request->user()?->tenant_id),实现租户/用户/设备三级隔离。 -
匿名高频接口(如短信发送):不能依赖登录态,建议组合字段生成 key,例如:
md5($request->ip() . $request->input('phone')),防止同一手机号被多 IP 轮询刷。
三、Nginx 层必须前置拦截
Laravel 处理请求有毫秒级延迟,攻击流量已进 PHP 就晚了。Nginx 是第一道防线:
- 用
limit_req_zone做漏桶限流,例如每秒最多 5 个请求,允许最多 10 个排队:limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;location /api/ { limit_req zone=api burst=10 nodelay; limit_req_status 429; } - 补充连接数限制:
limit_conn_zone $binary_remote_addr zone=conn:10m;+limit_conn conn 15;,防慢速连接耗尽资源。 - 简单 UA 过滤可快速屏蔽脚本工具:
if ($http_user_agent ~* "curl|httpie|python-requests") { return 403; }
四、复杂策略用 RateLimiter 自定义
内置 throttle:60,1 只能应付简单场景。真实业务需要差异化配额:
- 游客每分钟 10 次,登录用户每分钟 100 次,VIP 用户每分钟 500 次——在
RouteServiceProvider::configureRateLimiting()中注册: -
RateLimiter::for('api', function (Request $request) {
if ($user = $request->user()) {
return $user->is_vip ? Limit::perMinute(500) : Limit::perMinute(100);
}
return Limit::perMinute(10)->by($request->ip());}); - 关键点:每个
Limit::perXxx()必须带by()显式指定键,否则仍走默认 IP 键,且返回值必须是纯字符串(避免空格、斜杠等非法字符)。











