本文以生产可验证为目标,使用 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 的原生限流能力与简洁的熔断中间件,可以在高并发与下游不稳定的场景实现稳态吞吐与故障隔离;上述代码与参数均可在生产前的预发布环境完成验证与回归。

发表评论 取消回复