必须建立统一限流视图与共享计数器,所有服务使用相同Redis配置并验证连通性,通过shared:前缀确保key统一,路由层绑定throttle:shared-api中间件,支持租户或设备指纹隔离,并验证跨服务限流生效。

在微服务架构中,多个Laravel服务共用同一套API网关或共享下游资源(如Redis、数据库)时,单个服务内部限流无法阻止跨服务的总量超限,必须建立统一限流视图与共享计数器。
确认限流基础设施一致性
所有微服务必须使用同一套缓存后端,且驱动配置完全一致。检查每个服务的.env文件:【CACHE_DRIVER=redis】、【REDIS_HOST】、【REDIS_PORT】、【REDIS_PASSWORD】四项必须完全相同。若任一服务使用file或array驱动,该服务的限流将彻底失效且不报错,仅表现为“突然放行”。
运行php artisan tinker,执行cache()->store('redis')->get('test'),在每个服务中分别验证是否能读写同一key。失败即说明Redis连接未对齐。
定义全局统一限流键前缀
在每个微服务的App\Providers\AppServiceProvider的boot()方法中注册统一命名空间:
RateLimiter::for('shared-api', function ($request) {
return Limit::perMinute(300)->by('shared:'.$request->header('X-Request-ID') ?: $request->ip());
});
注意:这里强制添加shared:前缀,确保所有服务生成的缓存key都落在同一命名空间下,避免各服务各自为政。X-Request-ID由API网关注入,是跨服务请求唯一标识;未注入时回退到IP,但需确保网关已做真实IP透传。
路由层统一接入限流中间件
第一步:在每个微服务的app/Http/Kernel.php中,确认$middlewareGroups['api']已包含\Illuminate\Routing\Middleware\ThrottleRequests::class。
第二步:在各服务的routes/api.php中,对需统一管控的接口显式绑定命名策略:
Route::post('/order/submit', [OrderController::class, 'submit'])
->middleware('throttle:shared-api');
切勿使用硬编码形式如throttle:300,1,否则各服务独立计数,失去“统一”意义。
按业务维度隔离限流桶
方法一:基于租户ID隔离
当多租户共用同一套微服务集群时,在configureRateLimiting()中改写by逻辑:
return Limit::perMinute($tenant->rate_limit ?? 100)->by('tenant:'.$tenant->id);
注意:$tenant必须从请求上下文可靠获取,例如解析JWT中的tenant_id字段或从X-Tenant-ID头读取,不可依赖session或本地缓存。
方法二:基于设备指纹隔离
适用于APP端高频调用场景,防止单设备霸占配额:
->by('device:'.str_replace([' ', '/'], '-', $request->header('X-Device-Fingerprint')))
此操作会自动清洗非法字符,避免Redis key格式错误导致限流静默失效。
验证跨服务限流生效
① 启动服务A,调用/order/submit 299次(使用固定X-Request-ID)
② 立即切换至服务B,用相同X-Request-ID再次调用/order/submit
③ 第300次请求应立即返回HTTP 429响应,Header中含X-RateLimit-Remaining: 0和X-RateLimit-Reset
这一步验证完成。


















