feat: 增加IP限流器

This commit is contained in:
Ying
2023-08-02 18:18:21 +08:00
parent 295adfbd04
commit 91a16d4454

View File

@@ -0,0 +1,89 @@
<?php
namespace system;
use support\Cache;
/**
* 限流器
* Class RateLimiter
* @package system
*/
class RateLimiter
{
/**
* 基础限流名
*/
const TOKEN_LIMITER = 'token_limiter_';
/**
* 令牌桶限流名
*/
const RATE_LIMIT_BUCKET = 'rate_limit_bucket_';
/**
* 基础限流器
* @param string $name
* @param int $rate
* @return bool
*/
public static function baseLimit(string $name, int $rate = 10): bool
{
$bucketKey = self::TOKEN_LIMITER . $name;
$bucketData = Cache::get($bucketKey);
if (!$bucketData) {
$bucketData = [
'tokens' => $rate,
'lastRefillTime' => time()
];
Cache::set($bucketKey, $bucketData, 1);
}
$currentTime = time();
$timePassed = $currentTime - $bucketData['lastRefillTime'];
$tokensToAdd = $timePassed * $rate;
$tokensToAdd = min($tokensToAdd, $rate);
$bucketData['tokens'] += $tokensToAdd;
$bucketData['lastRefillTime'] = $currentTime;
if ($bucketData['tokens'] <= 0) {
return false;
}
$bucketData['tokens']--;
Cache::set($bucketKey, $bucketData, 1);
return true;
}
/**
* 令牌桶限流器
* @param string $name
* @param int $rate
* @param int $capacity
* @return bool
*/
public static function BucketLimit(string $name, int $rate = 10, int $capacity = 100): bool
{
$bucketKey = self::RATE_LIMIT_BUCKET . $name;
$bucketData = Cache::get($bucketKey);
if (!$bucketData) {
$bucketData = [
'tokens' => $capacity,
'lastRefillTime' => time()
];
Cache::set($bucketKey, $bucketData);
}
$currentTime = time();
$elapsedTime = $currentTime - $bucketData['lastRefillTime'];
$refillTokens = (int)($elapsedTime * $rate);
$bucketData['tokens'] = min($bucketData['tokens'] + $refillTokens, $capacity);
$bucketData['lastRefillTime'] = $currentTime;
if ($bucketData['tokens'] <= 0) {
return false;
}
$bucketData['tokens']--;
Cache::set($bucketKey, $bucketData);
return true;
}
}