namespace app\common\logic;
use think\Cache;
class RateLimitLogic {
public $ts;
public $cap;
public $limitAct;//限制的动作
public $result;
public function __construct() {
$this->result = ['errno' => 0, 'errmsg' => ''];
$this->ts = time();
$this->cap = C('rate_limit')['cap'];
$this->limitAct = C('rate_limit')['limit_act'];
foreach ($this->limitAct as &$v) {
$v > $this->cap && $v = $this->cap;
}
}
public function run($reqAct) {
if (!C('rate_limit')['on'] || !array_key_exists($reqAct, $this->limitAct)) {
return $this->result;
}
if (!file_exists(WWW_PATH.'/watching.log')) {
return ['errno' => 1, 'errmsg' => 'watching file gone away'];
}
$watching = file_get_contents(WWW_PATH.'/watching.log');
$arr = explode(" ", $watching);
$arrFilt = array_filter($arr, function ($item) {
return $item != "";
});
$apiRate = 0;
foreach ($arrFilt as $k => $v) {
if (strrpos($v, $reqAct) > 0) {
$apiRate = ceil($arrFilt[$k-1]/60);//设置60秒 脚本一分钟一次
break;
}
}
if ($apiRate > $this->limitAct[$reqAct]) {//该api每秒速率
Cache::watch($reqAct);
$limit = Cache::get($reqAct);
if (!empty($limit)) {
$token = min($this->cap, ($limit['num']-1)+($this->limitAct[$reqAct]*($this->ts-$limit['time'])));
if ($token < 0) {
plog('ratelimit.log', 'limit success', 'empty tokens');
return ['errno' => 1, 'errmsg' => '商城火爆,可稍等几分钟避开高峰期再试'];
}
$res = ['num' => $token, 'time' => $this->ts];
} else {
$res = ['num' => $this->cap, 'time' => time()];
}
Cache::multi();
Cache::set($reqAct, $res);
$end = Cache::exec();
if (!$end) {
plog('ratelimit.log', 'limit success', 'access too fast');
$this->result = ['errno' => 1, 'errmsg' => '访问频次过多'];
}
}
return $this->result;
}
}
令牌桶限流,亲测有效
最新推荐文章于 2024-08-11 14:24:05 发布
本文详细介绍了如何使用令牌桶算法实现PHP的流量限制。通过生成和消费令牌来控制请求速率,确保系统稳定运行。实际部署后,有效地防止了突发流量对服务器造成的影响。
摘要由CSDN通过智能技术生成