You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel API中Throttle限流未按预期工作

排查Laravel Throttle中间件误触发429的问题

你设置了throttle:10000,1(每分钟允许10000次请求)却仍收到429响应,大概率是限流计数逻辑或环境配置出了问题,按以下步骤排查:

1. 确认限流的计数维度

Laravel的Throttle中间件默认优先按认证用户ID统计请求数,若请求未通过认证,则切换为客户端IP计数:

  • 先检查webhook请求是否都正确通过auth:sanctum认证:如果存在未认证的请求,所有未认证请求会共用同一个IP的计数池,极易触发上限。
  • 可以强制自定义计数维度,比如用请求中的唯一标识(如webhook来源ID):
    // 路由中指定自定义限流规则名
    Route::post('webhook/update', [TaskController::class, 'update'])
        ->middleware([
            'auth:sanctum', 
            'verified',
            'throttle:10000,1,webhook_source'
        ]);
    
    然后在App\Providers\RouteServiceProvider中注册该规则的计数逻辑:
    use Illuminate\Cache\RateLimiting\Limit;
    use Illuminate\Support\Facades\RateLimiter;
    use Illuminate\Http\Request;
    
    public function boot()
    {
        RateLimiter::for('webhook_source', function (Request $request) {
            // 优先用请求头里的来源ID, fallback到IP
            $key = $request->header('X-Webhook-Source') ?: $request->ip();
            return Limit::perMinute(10000)->by($key);
        });
    }
    

2. 检查缓存驱动配置

Throttle的计数完全依赖缓存驱动,多服务器部署时要注意:

  • 禁止使用file缓存驱动:每个服务器会维护本地独立的缓存计数,单台服务器的请求量可能先达到上限,导致误触发429。
  • 切换到redis或memcached这类分布式缓存:所有服务器共享同一计数池,统计结果才会准确。
  • 可以临时打印缓存中的计数验证:
    use Illuminate\Support\Facades\Cache;
    
    public function update(Request $request)
    {
        // 计数键格式参考Laravel默认规则:throttle:{用户ID/IP}|{路由标识}
        $key = 'throttle:'.(auth()->id() ?: $request->ip()).'|webhook/update';
        dd('当前计数:'.Cache::get($key));
    }
    

3. 排查重复限流规则

检查路由是否被多个Throttle中间件覆盖:

  • 如果该路由属于某个路由组,而路由组本身也配置了throttle中间件,会导致双重限流,实际生效的是更严格的规则。
  • 运行php artisan route:list查看该路由的中间件列表,确认是否存在多个throttle条目。

4. 验证请求计数的准确性

在控制器中添加日志,直观查看每次请求的计数情况:

use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Cache\RateLimiting\Limit;

public function update(Request $request)
{
    $limiter = Limit::perMinute(10000)->by(auth()->id() ?: $request->ip());
    dd([
        '已请求次数' => RateLimiter::attempts($limiter->key($request)),
        '剩余可请求次数' => RateLimiter::remaining($limiter->key($request), 10000),
        '计数重置时间' => date('Y-m-d H:i:s', RateLimiter::availableAt($limiter->key($request)))
    ]);
}

5. 检查Laravel版本兼容性

部分旧版本Laravel(如8.x之前的部分分支)存在Throttle中间件计数未按时重置的bug,建议升级到对应分支的最新稳定版,查看官方release notes确认是否有相关修复。

内容的提问来源于stack exchange,提问作者Vikas Singhal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:50:27