2019-05-15 11:12:49 +08:00
|
|
|
# 令牌桶限流器
|
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
## 安裝
|
2019-05-15 11:12:49 +08:00
|
|
|
|
|
|
|
```bash
|
|
|
|
composer require hyperf/rate-limit
|
|
|
|
```
|
2019-12-12 16:24:04 +08:00
|
|
|
## 預設配置
|
2019-05-15 11:12:49 +08:00
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
| 配置 | 預設值 | 備註 |
|
2019-05-15 11:12:49 +08:00
|
|
|
|:--------------:|:------:|:-------------------:|
|
2019-12-12 16:24:04 +08:00
|
|
|
| create | 1 | 每秒生成令牌數 |
|
|
|
|
| consume | 1 | 每次請求消耗令牌數 |
|
2019-05-15 11:12:49 +08:00
|
|
|
| capacity | 2 | 令牌桶最大容量 |
|
2019-12-12 16:24:04 +08:00
|
|
|
| limitCallback | NULL | 觸發限流時回撥方法 |
|
2019-11-12 19:46:54 +08:00
|
|
|
| key | NULL | 生成令牌桶的 key |
|
2019-12-12 16:24:04 +08:00
|
|
|
| waitTimeout | 3 | 排隊超時時間 |
|
2019-05-15 11:12:49 +08:00
|
|
|
|
|
|
|
```php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
return [
|
|
|
|
'create' => 1,
|
|
|
|
'consume' => 1,
|
|
|
|
'capacity' => 2,
|
|
|
|
'limitCallback' => null,
|
|
|
|
'key' => null,
|
|
|
|
'waitTimeout' => 3,
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
## 使用限流器
|
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
元件提供 `Hyperf\RateLimit\Annotation\RateLimit` 註解,作用於類、類方法,可以覆蓋配置檔案。 例如,
|
2019-05-15 11:12:49 +08:00
|
|
|
|
|
|
|
```php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Controller;
|
|
|
|
|
|
|
|
use Hyperf\HttpServer\Annotation\Controller;
|
|
|
|
use Hyperf\HttpServer\Annotation\RequestMapping;
|
|
|
|
use Hyperf\RateLimit\Annotation\RateLimit;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Controller(prefix="rate-limit")
|
|
|
|
*/
|
|
|
|
class RateLimitController
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @RequestMapping(path="test")
|
|
|
|
* @RateLimit(create=1, capacity=3)
|
|
|
|
*/
|
|
|
|
public function test()
|
|
|
|
{
|
|
|
|
return ["QPS 1, 峰值3"];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @RequestMapping(path="test2")
|
|
|
|
* @RateLimit(create=2, consume=2, capacity=4)
|
|
|
|
*/
|
|
|
|
public function test2()
|
|
|
|
{
|
|
|
|
return ["QPS 2, 峰值2"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
2019-12-12 16:24:04 +08:00
|
|
|
配置優先順序 `方法註解 > 類註解 > 配置檔案 > 預設配置`
|
2019-05-15 11:12:49 +08:00
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
## 觸發限流
|
|
|
|
當限流被觸發時, 預設會丟擲 `Hyperf\RateLimit\Exception\RateLimitException` 異常
|
2019-05-15 11:12:49 +08:00
|
|
|
|
2019-12-12 16:41:17 +08:00
|
|
|
可以通過[異常處理](zh-tw/exception-handler.md)或者配置 `limitCallback` 限流回調處理。
|
2019-06-20 11:31:26 +08:00
|
|
|
|
|
|
|
例如:
|
2019-05-15 11:12:49 +08:00
|
|
|
```php
|
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Controller;
|
|
|
|
|
|
|
|
use Hyperf\Di\Aop\ProceedingJoinPoint;
|
|
|
|
use Hyperf\HttpServer\Annotation\Controller;
|
|
|
|
use Hyperf\HttpServer\Annotation\RequestMapping;
|
|
|
|
use Hyperf\RateLimit\Annotation\RateLimit;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @Controller(prefix="rate-limit")
|
2019-08-28 11:42:06 +08:00
|
|
|
* @RateLimit(limitCallback={RateLimitController::class, "limitCallback"})
|
2019-05-15 11:12:49 +08:00
|
|
|
*/
|
|
|
|
class RateLimitController
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @RequestMapping(path="test")
|
|
|
|
* @RateLimit(create=1, capacity=3)
|
|
|
|
*/
|
|
|
|
public function test()
|
|
|
|
{
|
|
|
|
return ["QPS 1, 峰值3"];
|
|
|
|
}
|
|
|
|
|
2019-06-20 11:31:26 +08:00
|
|
|
public static function limitCallback(float $seconds, ProceedingJoinPoint $proceedingJoinPoint)
|
2019-05-15 11:12:49 +08:00
|
|
|
{
|
2019-12-12 16:24:04 +08:00
|
|
|
// $seconds 下次生成Token 的間隔, 單位為秒
|
|
|
|
// $proceedingJoinPoint 此次請求執行的切入點
|
|
|
|
// 可以通過呼叫 `$proceedingJoinPoint->process()` 繼續執行或者自行處理
|
2019-06-20 11:31:26 +08:00
|
|
|
return $proceedingJoinPoint->process();
|
2019-05-15 11:12:49 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 11:42:06 +08:00
|
|
|
```
|