Laravel 8如何基于数据库配置动态设置rate limiter速率限制
实现方案
1. 准备对应数据表的Eloquent模型
先创建模型对应你的限流规则表,假设你的表名为rate_limit_rules,模型代码示例:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class RateLimitRule extends Model { // 如果实际表名不是rate_limit_rules请手动指定 protected $table = 'rate_limit_rules'; // 允许批量赋值的字段 protected $fillable = [ 'key', 'param_1', 'param_2', 'param_3', 'rate_limit' ]; // 如果你的表没有created_at、updated_at字段请关闭自动时间戳 public $timestamps = false; }
如果你数据库原字段是带空格的命名(如
Param 1),查询时设置别名和模型属性对应即可。
2. 重写RateLimiter配置
修改app/Providers/RouteServiceProvider.php中的configureRateLimiting方法,代码如下:
<?php use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\Cache; use App\Models\RateLimitRule; use Illuminate\Http\Request; protected function configureRateLimiting() { RateLimiter::for('api', function (Request $request) { // 缓存限流规则1小时,避免每次请求都查询数据库,有效期可自行调整 $limitRules = Cache::remember('dynamic_rate_limit_rules', 3600, function () { return RateLimitRule::all(['key', 'param_1', 'param_2', 'param_3', 'rate_limit']); }); $limits = []; // 遍历数据库规则动态生成限流实例 foreach ($limitRules as $rule) { // 按照要求拼接限流key:key_param1_param2_param3 $rateKey = implode('_', [ $rule->key, $rule->param_1, $rule->param_2, $rule->param_3 ]); $limits[] = Limit::perMinute($rule->rate_limit) ->by($rateKey) ->response(function () { // 这里保留你原有的自定义限流触发后的响应逻辑 return response()->json([ 'code' => 429, 'message' => '请求过于频繁,请稍后再试' ], 429); }); } // 可选:添加默认限流规则,避免数据库无规则时完全不限流 $limits[] = Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); return $limits; }); }
3. 注意事项
- 如果你在后台更新了限流规则,需要清理对应缓存
Cache::forget('dynamic_rate_limit_rules')才会生效,也可以直接在规则的新增/修改/删除逻辑中加入清缓存的操作。 - 所有规则的限流是同时生效的,只要任意一个规则触发限流就会返回429响应。
内容的提问来源于stack exchange,提问作者Mahe Krish
相关产品推荐
相关产品推荐

