php令牌桶,令牌桶限频(TokenBucket)

php令牌桶,令牌桶限频(TokenBucket)高可用对于一个应用和 API 接口是至关重要的 如果我们提供一个接口 突然面临流量爆发式增长 对于这种情况 不仅会影响网站的访问速度 甚至可能会导致服务器崩溃 使得所有用户都无法正常访问 对于这种情况 有的同学认为 我们可以通过提高配置或者增加机器去解决这样的问题 这在某些情况下 确实是一种选择 然而当我们使用一个接口或应用时 我们不仅需要通过技术手段 幂等性 熔断等 去提高它们的稳定性 同时也确

bVbEXu5

高可用对于一个应用和API接口是至关重要的。如果我们提供一个接口,突然面临流量爆发式增长,对于这种情况,不仅会影响网站的访问速度,甚至可能会导致服务器崩溃,使得所有用户都无法正常访问。

对于这种情况,有的同学认为:“我们可以通过提高配置或者增加机器去解决这样的问题”。这在某些情况下,确实是一种选择。然而当我们使用一个接口或应用时,我们不仅需要通过技术手段(幂等性、熔断等)去提高它们的稳定性,同时也确保因为其他突发原因(如新同事编写的代码导致意外的发生等)带来的问题。

以下几种情况,频率限制可以帮助我们更好的确保API的可用性:

用户使用脚本,向我们发送了大量的请求。

用户向我们发送了许多低优先级接口数据的请求,而我们希望这些低优先级的请求尽量不影响我们高优先级接口请求(如电商,必须保证下单流程是正常的,其他的接口优先级自然低于下单流程相关的接口)。

因突然原因,无法同时正常访问所有接口,因此需要临时丢弃优先级低的请求(当然Nginx层面也是可以实现的)。

令牌桶介绍

令牌桶算法的原理是系统会以一个恒定的速度往桶(bucket)放入令牌(token),而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务(denial of service)。

特点:

当bucket满的时候,将不再放入token,也就是token数量不会超过bucket最大容量。

由于token在一段时间内是有限的,所以即使发生突然流量,也能很好的保护服务。

实现方式

对于令牌桶的实现,一般常用的有两种:

第一种

后台启动一个线程,按照一定的时间颗粒度,不断的往固定大小的桶(bucket)增加令牌(token),直到达到桶的最大容量。

这种做法不仅实现稍微繁琐一点,需要额外维护一个脚本;而且在没有请求的情况下,线程也会不断的去检查更新token,如果key比较多的情况下,对CPU会有较大的性能影响。

第二种(本文案例)

每次访问,将本次访问的时间和速率存入redis,并在下次新的请求访问时,对比当前时间和上次请求时间两个时间差之间的可使用token数量,并将新的结果存入redis。

代码实现

initNum 桶初始大小

expire单位时间

nowTime 当前访问的时间

limitData[‘time’] 上次请求的时间

namespace app\components;

use yii\base\Component;

class RateLimiter extends Component

{

public $redis = null;

public $cacheKey = null;

// number of visits per minute by a single user

// 单位时间下,单个用户访问的次数

public $initNum = 30;

// unit time

// 单位时间

public $expire = 60;

/

* RateLimiter constructor.

* @param string $initNum

* @param string $expire

*/

public function __construct($cacheKey = ”, $initNum = ”, $expire = ”)

{

if (empty($cacheKey)) {

return false;

}

$this->redis = \Yii::$app->redis;

$this->initNum = $initNum ?? $this->initNum;

$this->expire = $expire ?? $this->expire;

$this->cacheKey = $cacheKey;

}

/

* handler

* @return array

*/

public function handler()

{

$ret = self::_limit($this->cacheKey, $this->initNum, $this->expire);

if (empty($ret[‘status’])) {

return false;

}

return true;

}

private function _limit($cacheKey = ”, $initNum = ”, $expire = ”)

{

$nowTime = time();

$this->redis->watch($cacheKey);

$redisData = $this->redis->get($cacheKey);

$limitData = $redisData ? json_decode($redisData, true) : [‘num’ => $initNum, ‘time’ => $nowTime];

// (单位时间访问频率 / 单位时间)*(当前时间 – 上次访问时间) = 上次请求至今可增加的访问次数

$addNum = ($initNum / $expire) * ($nowTime – $limitData[‘time’]);

$newNum = min($initNum, (($limitData[‘num’] – 1) + $addNum));

if ($newNum <= 0) {

return [‘status’ => false, ‘msg’ => ‘当前时刻令牌用完啦!’];

}

$limitData = json_encode([‘num’ => $newNum, ‘time’ => $nowTime]);

$this->redis->multi();

$this->redis->set($cacheKey, $limitData);

if (!$this->redis->exec()) {

return [‘status’ => false, ‘msg’ => ‘访问频次过多!’];

}

return [‘status’ => true, ‘msg’ => ‘ok’];

}

}

总结

令牌桶频率限制是API接口设计中重要的安全策略之一,但是对于不同的业务和场景都应该使用最适合的方法(如登录密码错误,一天只能尝试五次,这种情况计数器限频就是更好的选择了),万事并无绝对。

参考

https://medium.com/smyte/rate-limiter-df

https://stripe.com/en-hk/blog/rate-limiters

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/177578.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午7:11
下一篇 2026年3月26日 下午7:11


相关推荐

  • Wappalyzer 网站技术分析软件「建议收藏」

    Wappalyzer 网站技术分析软件「建议收藏」Wappalyzer工具支持分析目标网站所采用的平台构架、网站环境、服务器配置环境、JavaScript框架、编程语言等参数,同时还可以显示目标站点使用该技术的网站比例,例如有多少网站使用的是Wordpress、有多少网站使用AddThis第三方服务,其他还有网页服务器、分析工具、CDN、留言系统、控制台、网络空间等等,可以让你从使用比例中得出目前最流行的技术。使用方法:1.打开

    2022年5月12日
    79
  • QGIS 3.10 路径分析

    QGIS 3.10 路径分析网络数据集(networks)的创建、管理和可视化是GIS的重要组成部分。公路、铁路、管线等公用基础设施都可以建模为由线和节点组成的带有属性信息的网络数据。本教程将学习如何对路网进行建模,如何运用样式对路网属性可视化,同时通过QGIS3.10内置的路径分析工具找出两点之间的最短路径。任务概述通过华盛顿地区道路中心线图层,建立路网并查找城市中任意两点之间的最短路径。将会学到的其他技巧使用数据定义覆盖(datadefinedoverrides),根据线的方向对齐箭头符号。获取示范数据本教程

    2022年8月24日
    12
  • 科大讯飞正式发布星火X2大模型 2025年大模型相关项目中标金额达23.16亿元

    科大讯飞正式发布星火X2大模型 2025年大模型相关项目中标金额达23.16亿元

    2026年3月14日
    2
  • 关于C语言中fseek函数的使用

    关于C语言中fseek函数的使用关于 C 语言中

    2026年3月19日
    1
  • 浙江八年级 python_今年9月起,浙江八年级新增Python编程课程

    浙江八年级 python_今年9月起,浙江八年级新增Python编程课程今年9月的新学期,浙江三到九年级信息技术课将替换新教材。消息一出,引起浙江学生家长的关注。其中最大的变化是,八年级将新增Python课程内容。新高一信息技术编程语言由VB替换为Python,大数据、人工智能、程序设计与算法按照教材规划五六年级开始接触。浙江省教研室相关工作人员表示,目前根据现行的高中教材,对小学、初中的老教材进行了修订,新教材将于今年9月投入使用,最新的线上教师培训也刚刚结束。在最…

    2022年5月17日
    46
  • Python之Flask框架:Flask框架简介、安装、使用方法详细攻略

    Python之Flask框架:Flask框架简介、安装、使用方法详细攻略Python 之 Flask 框架 Flask 框架简介 安装 使用方法详细攻略目录 Flask 框架简介 Flask 框架安装 Flask 框架使用方法 1 小试牛刀 然后访问 UR 即可得到 LFlask 框架简介对初学者来说 循序渐进是最重要的 我推荐学习 Flask Welcome Flask APythonMicro

    2026年3月26日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号