在当今的互联网应用中,API(应用程序接口)的使用越来越广泛。为了保证 API 的稳定性和性能,限流是一个非常重要的措施。限流可以防止 API 被过度调用,避免系统资源被耗尽,同时也可以保护 API 免受恶意攻击。ThinkPHP 是一个流行的 PHP 框架,它提供了多种方式来实现 API 限流。本文将介绍 ThinkPHP 中实现 API 限流的方法和技巧。
一、使用中间件实现限流
ThinkPHP 提供了中间件机制,我们可以通过编写中间件来实现 API 限流。中间件是位于 HTTP 请求和响应处理链之间的组件,它可以对请求进行预处理和响应后处理。以下是一个使用中间件实现 API 限流的示例代码:
```php
use think\facade\Cache;
use think\middleware\BaseMiddleware;
class ApiRateLimitMiddleware extends BaseMiddleware
{
public function handle($request, \Closure $next)
{
$apiKey = $request->header('X-API-Key');
if (empty($apiKey)) {
return json(['code' => 401, 'message' => 'API key is missing']);
}
$limit = 100; // 限制每秒调用次数
$interval = 1; // 时间间隔(秒)
$cacheKey = "api_rate_limit_{$apiKey}";
$currentTime = time();
$cacheValue = Cache::get($cacheKey);
if ($cacheValue && $currentTime - $cacheValue < $interval) {
return json(['code' => 429, 'message' => 'Too many requests']);
}
Cache::set($cacheKey, $currentTime, $interval);
return $next($request);
}
}
```
在上述代码中,我们创建了一个名为 `ApiRateLimitMiddleware` 的中间件类,继承自 `BaseMiddleware`。在 `handle` 方法中,我们首先从请求头中获取 `X-API-Key`,如果没有则返回 401 错误。然后,我们设置了限流的限制次数为每秒 100 次,时间间隔为 1 秒。接下来,我们使用缓存来记录每个 API 密钥的调用时间,如果在时间间隔内已经有调用,则返回 429 错误。我们将当前时间设置为缓存值,并返回下一个中间件或控制器的处理结果。
要使用这个中间件,我们需要在 `app/http/kernel.php` 文件中的 `$middleware` 数组中添加中间件:
```php
'middleware' => [
// 其他中间件
\app\middleware\ApiRateLimitMiddleware::class,
],
```
这样,所有的 API 请求都会经过这个中间件的处理,实现了 API 限流的功能。
二、使用第三方库实现限流
除了使用 ThinkPHP 自带的中间件机制,我们还可以使用第三方库来实现 API 限流。ThinkPHP 支持 Composer 依赖管理,我们可以通过 Composer 安装一些流行的限流库,如 `throttle`、`swoole/throttle` 等。
以下是使用 `throttle` 库实现 API 限流的示例代码:
```php
use think\facade\Cache;
use Hyperf\Throttle\Limit;
use Hyperf\Throttle\RateLimiterInterface;
use Hyperf\Utils\ApplicationContext;
class ApiRateLimit
{
public function __construct(
private RateLimiterInterface $limiter
) {
}
public function handle($request, \Closure $next)
{
$apiKey = $request->header('X-API-Key');
if (empty($apiKey)) {
return json(['code' => 401, 'message' => 'API key is missing']);
}
$limit = new Limit(100, 1); // 限制每秒调用次数为 100
if (!$this->limiter->tryConsume($apiKey, $limit)) {
return json(['code' => 429, 'message' => 'Too many requests']);
}
return $next($request);
}
}
```
在上述代码中,我们创建了一个名为 `ApiRateLimit` 的类,其中包含一个构造函数和一个 `handle` 方法。在构造函数中,我们通过依赖注入获取了 `RateLimiterInterface` 的实例。在 `handle` 方法中,我们首先从请求头中获取 `X-API-Key`,如果没有则返回 401 错误。然后,我们创建了一个 `Limit` 对象,设置了限制每秒调用次数为 100。接下来,我们使用 `tryConsume` 方法尝试消耗一个令牌,如果令牌不足则返回 429 错误。我们返回下一个中间件或控制器的处理结果。
要使用这个类,我们需要在 `app/http/kernel.php` 文件中的 `$middleware` 数组中添加中间件:
```php
'middleware' => [
// 其他中间件
\app\middleware\ApiRateLimit::class,
],
```
同时,我们还需要在项目的 `composer.json` 文件中添加 `hyperf/throttle` 库的依赖:
```json
"require": {
"hyperf/throttle": "^1.0"
}
```
然后,执行 `composer install` 命令来安装依赖。
三、总结
限流是保证 API 稳定性和性能的重要措施,ThinkPHP 提供了多种方式来实现 API 限流。我们可以使用中间件机制来编写自定义的限流逻辑,也可以使用第三方库来简化限流的实现。在实际应用中,我们可以根据具体的需求和场景选择合适的限流方式,并根据实际情况进行调整和优化。通过合理的限流设置,可以有效地防止 API 被过度调用,保护系统资源,提高 API 的可用性和稳定性。