throttle中间件仅限制客户端对路由的访问频率,无法控制后端代码循环调用外部api的行为;需通过cache::add、redis原子计数、封装限流http客户端或利用第三方api原生限流头等方式手动实现出向请求限流,并确保缓存驱动为redis等共享存储。

throttle中间件对循环调用外部API无效
直接给调用外部 API 的路由加 throttle:60,1 没用——它限制的是「客户端请求该接口的频率」,不是「你的后端代码调用第三方服务的频率」。你写个 for 循环在控制器里发 100 次 Http::get(),throttle 完全感知不到,只会计 1 次请求(来自前端)。
真正要限的是你的服务端出向请求
你需要控制的是 Laravel 应用自身对外部 API 的调用频次,常见场景包括:定时任务批量拉取、用户触发后循环查多个 ID、Webhook 回调重试等。这时得绕过 throttle 中间件,自己管住出向流量:
- 用
Cache::add()实现“单次写入”锁机制,比如cache_add("ext_api_rate:github", 1, 60),失败说明 1 分钟内已调用过 - 基于 Redis 的
INCR+EXPIRE手动计数,构造键如ext:github:2026-06-12-04,配合 Lua 脚本保证原子性 - 封装一个带限流逻辑的 HTTP 客户端类,在
send()前检查配额,比在每个控制器里重复写逻辑更可靠 - 若第三方 API 支持 token bucket 或 client_id 维度配额,优先用其原生限流头(如
X-RateLimit-Remaining),再结合Cache::put()缓存响应头里的剩余次数
别踩 cache driver 为 array 的坑
本地开发常用 array 缓存驱动,但它不支持跨进程共享状态。你在 Artisan 命令里跑循环调用,和 Web 请求用的是两套独立内存,Cache::get() 根本不互通。上线前必须确认:
-
config/cache.php中default是redis或database -
throttle中间件底层也依赖这个缓存 store,所以它失效往往是因为 cache 配置没对齐 - 用
php artisan tinker执行Cache::store('redis')->increment('test')验证 Redis 连通性
RateLimiter 策略名必须显式注册
哪怕你只是想用 throttle:60,1 临时限制某个内部命令的调用入口,也得先在 App\Providers\RouteServiceProvider::configureRateLimiting() 里注册策略名。否则会报错 Rate limiter [api] is not defined,或者静默失效——尤其当这个命令被 Artisan 调用时,没有路由上下文,中间件根本不会初始化。
复杂点在于:限流键要能区分「谁在调」。比如同一个命令由不同租户触发,就得用 by($tenant->id);如果是定时任务,建议固定键 + 时间窗口,避免租户隔离干扰调度逻辑。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











