diff --git a/extend/system/RateLimiter.php b/extend/system/RateLimiter.php new file mode 100644 index 0000000..78e2a51 --- /dev/null +++ b/extend/system/RateLimiter.php @@ -0,0 +1,89 @@ + $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; + } +} \ No newline at end of file