Laravel 11 中使用 Redis::throttle 进行速率限制

在 Laravel 11 中,Redis::throttle 是一个强大的工具,用于实现对 API 或特定操作的速率限制。通过使用 Redis 作为后端存储,Redis::throttle 可以有效地控制用户在一定时间内可以执行的请求次数。本文将介绍如何使用 Redis::throttle,其主要方法、注意事项,并与 RateLimiter 进行对比。

1. Redis::throttle 的基本使用

Redis::throttle 是 Laravel 提供的一个基于 Redis 的速率限制工具。它允许你轻松地限制某个操作在特定时间内的执行次数。

1.1 基本语法

use Illuminate\Support\Facades\Redis;

Redis::throttle('key')->allow(10)->every(60)->then(function () {
// 正常执行操作
}, function () {
// 超过速率限制时的回调
});
  • key: 用于标识速率限制的唯一键。
  • allow(10): 在指定的时间窗口内允许的最大请求次数。
  • every(60): 时间窗口的长度(以秒为单位)。
  • then: 当请求未超过限制时执行的回调。
  • 第二个回调函数是可选的,用于处理超过限制时的逻辑。

1.2 示例

假设你希望限制用户每分钟只能发送 5 条消息:

use Illuminate\Support\Facades\Redis;

Redis::throttle('send-message:' . $user->id)->allow(5)->every(60)->then(function () use ($user) {
// 发送消息的逻辑
$this->sendMessage($user, $message);
}, function () {
// 超过限制时的处理
return response('Too many attempts. Please try again later.', 429);
});

在这个例子中,send-message: 加上用户 ID 作为键,确保每个用户的速率限制是独立的。

2. 主要方法

2.1 allow(int $maxAttempts)

设置在一定时间窗口内允许的最大请求次数。

2.2 every(int $decaySeconds)

设置时间窗口的长度(以秒为单位)。

2.3 then(callable $callback, callable $failureCallback = null)

  • $callback: 当请求未超过限制时执行的回调。
  • $failureCallback: 当请求超过限制时执行的回调(可选)。

2.4 block(int $timeout)

设置当请求超过限制时,阻塞用户的时间(以秒为单位)。在这段时间内,用户无法再次发起请求。

Redis::throttle('key')->allow(10)->every(60)->block(10)->then(function () {
// 正常执行操作
}, function () {
// 超过速率限制时的回调
});

在这个例子中,如果用户超过了速率限制,他们将被阻塞 10 秒。

3. 注意事项

3.1 Redis 连接

确保你的 Laravel 应用已经正确配置了 Redis 连接。你可以在 .env 文件中设置 REDIS_HOSTREDIS_PASSWORD 等参数。

3.2 键的唯一性

Redis::throttle 的键必须是唯一的,通常你会使用用户 ID、IP 地址或其他唯一标识符来构造键。

3.3 阻塞时间

使用 block 方法时,确保设置的阻塞时间合理,避免用户长时间无法操作。

3.4 分布式环境

在分布式环境中,Redis::throttle 可以很好地工作,因为 Redis 是一个集中式的存储系统。确保所有服务器都连接到同一个 Redis 实例。

4. 与 RateLimiter 的对比

Laravel 还提供了 RateLimiter 工具,它与 Redis::throttle 类似,但有一些区别:

4.1 配置方式

RateLimiter 通常在 app/Providers/RouteServiceProvider.php 中配置,而 Redis::throttle 可以在代码中直接使用。

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

RateLimiter::for('api', function ($request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});

4.2 灵活性

Redis::throttle 更加灵活,可以在任何地方使用,而 RateLimiter 通常用于路由中间件中。

4.3 使用场景

  • Redis::throttle 更适合在代码中直接控制速率限制,例如在服务类或控制器中。一般是分钟级别。
  • RateLimiter 更适合在全局范围内对路由进行速率限制。秒级。

4.4 性能

两者都基于 Redis,性能差异不大。选择使用哪个工具主要取决于你的使用场景和偏好。

5. 总结

Redis::throttle 是 Laravel 中一个非常实用的速率限制工具,特别适合在代码中直接控制操作的执行频率。通过合理使用 alloweveryblock 方法,你可以轻松实现对用户请求的限制。与 RateLimiter 相比,Redis::throttle 更加灵活,适合在特定场景下使用。

在实际开发中,根据需求选择合适的工具,可以有效提升应用的稳定性和用户体验。