webman限流器,支持注解限流。
支持apcu、redis、memory驅(qū)動。
https://github.com/webman-php/rate-limiter
composer require webman/rate-limiter
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;
use Webman\RateLimiter\Limiter;
class UserController
{
#[RateLimiter(limit: 10)]
public function index(): string
{
// 默認(rèn)為IP限流,默認(rèn)單位時間為1秒
return '每個ip每秒最多10個請求';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID,以用戶ID為維度進(jìn)行限流,要求session('user.id')不為空
return '每個用戶60秒最多100次搜索';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: '每人每分鐘只能發(fā)1次郵件')]
public function sendMail(): string
{
// key: RateLimiter::SID,以session_id為維度進(jìn)行限流
return '郵件發(fā)送成功';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: '今天的優(yōu)惠券已經(jīng)發(fā)完,請明天再來')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: '每個用戶每天只能領(lǐng)取一次優(yōu)惠券')]
public function coupon(): string
{
// key: 'coupon', 這里coupon為自定義key,也就是全局以coupon為key進(jìn)行限流,每天最多發(fā)100張優(yōu)惠券
// 同時以用戶ID為維度進(jìn)行限流,每個用戶每天只能領(lǐng)取一次優(yōu)惠券
return '優(yōu)惠券發(fā)送成功';
}
public function sendSms(string $mobile): string
{
// 當(dāng)key為變量時,可以使用如下代碼手動限流,這里mobile作為key
Limiter::check($mobile, 5, 24*60*60, '每個手機(jī)號一天最多5條短信');
return '短信發(fā)送成功';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: '每個手機(jī)號一天最多5條短信')]
public function sendSms2(): string
{
// 當(dāng)key為變量時,可以使用[類, 靜態(tài)方法]的方式獲取key,例如[UserController::class, 'getMobile']會調(diào)用UserController的getMobile()方法的返回值為key
return '短信發(fā)送成功';
}
/**
* 自定義key,獲取手機(jī)號,必須是靜態(tài)方法
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: '頻率受限', exception: RuntimeException::class)]
public function testException(): string
{
// 超限默認(rèn)異常為Webman\RateLimiter\RateLimitException,可以通過exception參數(shù)更改
return 'ok';
}
}
說明
ttl:60
為60秒127.0.0.1
不限流,參見下面配置部分)session('user.id')
不為空),SID限流(根據(jù)session_id
限流)X-Forwarded-For
頭,參見nginx代理Webman\RateLimiter\RateLimitException
異常,可通過exception:xx
來自定義異常類Too Many Requests
,可通過message:xx
自定義錯誤信息composer require symfony/translation
mkdir resource/translations/zh_CN/ -p
echo "<?php
return [
'Too Many Requests' => '請求頻率受限'
];" > resource/translations/zh_CN/messages.php
php start.php restart
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// 這些ip的請求不做頻率限制(只有在key為 RateLimiter::IP 時有效)
'ip_whitelist' => [
'127.0.0.1',
],
];
auto
apcu
memory
redis
中的一個值,使用auto
時會自動在apcu
和memory
中選一個值redis
配置,connection
對應(yīng)config/redis.php
中對應(yīng)的key
RateLimiter::IP
時有效)memory
介紹
無需安裝任何擴(kuò)展,性能最好。
使用限制
限流只對當(dāng)前進(jìn)程有效,多個進(jìn)程間不共享限流數(shù)據(jù),同時也不支持集群限流。
試用場景
windows開發(fā)環(huán)境;不需要嚴(yán)格限流的業(yè)務(wù);抵御CC攻擊時。
apcu
安裝擴(kuò)展
當(dāng)driver使用apcu時,需要安裝apcu擴(kuò)展,并且php.ini中設(shè)置
apc.enabled=1
apc.enable_cli=1
如果不知道php.ini位置,可以通過命令php --ini
尋找php.ini的位置
介紹
性能略低于memory,支持多進(jìn)程共享限流數(shù)據(jù)。
使用限制
不支持集群
使用場景
任何開發(fā)環(huán)境;線上單機(jī)限流場景;集群不需要嚴(yán)格限流的場景;抵御CC攻擊。
redis
依賴
需要安裝redis擴(kuò)展,并安裝Redis組件,安裝命令
composer require -W illuminate/redis illuminate/events
介紹
性能低于apcu,支持單機(jī)也支持集群精確限流
適用場景
開發(fā)環(huán)境;線上單機(jī)環(huán)境;集群環(huán)境
webman v1文檔也有限流器的介紹,安裝不了這個限流器,看了只支持php8.0及以上
啥時候都支持下咯,更新速度太快了 越來越感覺跟不上大佬的節(jié)奏了
能否在header里顯示以下內(nèi)容?
X-Rate-Limit-Limit
X-Rate-Limit-Remaining
X-Rate-Limit-Reset