本文以生产可验证为目标,使用 Laravel 10 的 `RateLimiter`/`ThrottleRequests` 配合 Redis 实现按用户/接口维度的令牌桶限流,并设计简洁的熔断器逻辑以隔离故障与快速失败。


## 环境与前提


  • PHP 8.2/8.3,Laravel 10.x。
  • Redis 6/7,驱动 `phpredis` 或 `predis`。

## 令牌桶限流(按用户维度)


在 `App\Providers\AppServiceProvider` 中定义限流规则:


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

public function boot(): void
{
    RateLimiter::for('api-user', function ($request) {
        $key = sprintf('api:%s', $request->user()?->id ?? $request->ip());
        return [
            Limit::perMinute(120)->by($key)->response(function () {
                return response()->json([
                    'code' => 429,
                    'message' => 'Too Many Requests'
                ], 429);
            }),
        ];
    });
}

在路由中应用中间件:


Route::middleware(['throttle:api-user'])->group(function () {
    Route::get('/v1/orders', [OrderController::class, 'index']);
});

验证命令:


ab -n 500 -c 50 http://localhost/api/v1/orders

观察 `429` 比例与应用日志,确认限流生效。


## Redis 驱动与精细化控制


`.env`:


REDIS_CLIENT=phpredis
CACHE_STORE=redis

`config/cache.php` 与 `config/database.php` 中确保 Redis 连接分离(缓存/会话/限流统计使用不同 DB)。


## 熔断器(简易实现,可验证)


思路:对下游依赖(如支付网关)进行失败计数与时间窗控制,达到阈值后短路一定时间再尝试半开恢复。


中间件示例(`app/Http/Middleware/CircuitBreaker.php`):


namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Cache;

class CircuitBreaker
{
    public function handle($request, Closure $next, string $name, int $failMax = 10, int $coolDown = 30)
    {
        $stateKey = "cb:{$name}:state"; // open|half|closed
        $failKey  = "cb:{$name}:fail";

        $state = Cache::get($stateKey, 'closed');
        if ($state === 'open') {
            return response()->json(['code' => 503, 'message' => 'Service Unavailable'], 503);
        }

        $response = $next($request);
        if ($response->getStatusCode() >= 500) {
            $fails = Cache::increment($failKey);
            if ($fails >= $failMax) {
                Cache::put($stateKey, 'open', $coolDown);
            }
        } else {
            Cache::forget($failKey);
        }

        return $response;
    }
}

应用:


Route::middleware(['circuit:paygw,10,30','throttle:api-user'])
    ->post('/v1/pay', [PayController::class, 'create']);

验证:模拟下游 500 错误并观察 503 短路行为,30 秒后自动恢复半开状态。


## 压测与监控建议


  • 使用 `wrk`/`k6` 对关键接口压测,记录 `RPS` 与 `p95/p99`。
  • 采集 Redis `INFO` 与命令统计,确认限流与熔断键命中情况。
  • 结合应用日志与 APM(如 OpenTelemetry)观测短路比例与恢复耗时。

## 注意事项


  • 令牌桶速率需结合业务基线与峰值流量设置,避免误杀。
  • 熔断逻辑需在业务层保证幂等与回退方案(重试/队列)。
  • 多实例部署时,请确保 Redis 键统一,避免状态不一致。

## 结语


借助 Laravel 10 的原生限流能力与简洁的熔断中间件,可以在高并发与下游不稳定的场景实现稳态吞吐与故障隔离;上述代码与参数均可在生产前的预发布环境完成验证与回归。



点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部