限流中间件未生效主因是未正确配置中间件组:默认仅在api组启用,web路由需显式添加middleware('throttle:60,1');参数为每分钟请求数上限与时间窗口(分钟);未登录用户按ip、登录用户按id限流(需auth中间件);自定义响应需修改handler::render();缓存须用redis等共享驱动,array驱动多机失效;redis不可用时会静默退化为不限流。

限流中间件没生效?检查 throttle 是否在正确中间件组里
默认的 throttle 中间件只在 api 中间件组中启用,如果你走的是 web 路由(比如登录页、首页),它压根不会触发。Laravel 不会自动把限流加到所有请求上。
- 确认路由是否用了
middleware('api'),或者手动加->middleware('throttle:60,1') -
web路由要限流,必须显式绑定,不能依赖默认行为 - 别在
app/Http/Kernel.php的$middlewareGroups['web']里硬塞throttle—— 它依赖请求里的Route实例和认证状态,放错位置会报Route not found或静默失效
throttle:60,1 的两个参数到底控制什么
第一个是「请求数上限」,第二个是「时间窗口(分钟)」,不是秒,也不是小时。很多人误以为 throttle:5,60 是“每小时5次”,其实它是“每60分钟5次”,但 Laravel 内部用的是分钟单位,所以等价于 throttle:5,60;而 throttle:5,1 才是“每分钟5次”。
- 时间窗口只支持整数分钟,不支持
0.5或30秒这种写法 - 若想实现“每30秒最多1次”,得写成
throttle:2,1(即每分钟最多2次),再配合前端防抖,没有原生秒级精度 - 该规则对未登录用户按 IP 限流,对已登录用户按
id限流——前提是路由绑定了auth中间件,否则全按 IP
自定义限流响应被忽略?重写 handle 前先看异常是否被捕获
直接在控制器里 throw ThrottleRequestsException 不会触发你自定义的响应逻辑,因为 throttle 中间件内部捕获并处理了这个异常。真要改返回内容,得去覆盖 App\Exceptions\Handler::render() 里对 ThrottleRequestsException 的处理分支。
- 不要在中间件里 try/catch
ThrottleRequestsException—— 它早被框架吞掉了 - 修改响应体推荐用 JSON 格式,尤其是 API 场景;
web路由返回重定向或视图容易和 session 冲突 - 注意缓存驱动:如果用的是
array缓存,限流在多机器部署下完全失效,必须切到redis或memcached
Redis 连接失败导致限流彻底失效,但日志里可能没报错
Laravel 的 throttle 在 Redis 不可用时会悄悄退化为「不限流」,而不是抛异常中断请求。这是为了保障服务可用性,但对安全敏感场景是隐患。
- 检查
config/cache.php中default是否指向了真实可用的 Redis 配置 - 运行
php artisan tinker,执行Cache::store('redis')->get('test')和set('test', 'ok')验证连通性 - 线上建议加健康检查端点,读取
cache驱动状态,而不是只盯redis进程是否存活
限流的边界情况比想象中多:IP 可伪造、用户 ID 可绕过、缓存驱逐策略会影响窗口计数。上线前最好用 ab 或 hey 模拟并发压测真实路径,别只信单元测试里的 mock。











