Spring Cloud Gateway中一段脚本如何实现令牌桶


这篇文章将为大家详细讲解有关Spring Cloud Gateway中一段脚本如何实现令牌桶,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在一个分布式高并发的系统设计中,限流是一个不可忽视的功能点。如果不对系统进行有效的流量访问限制,在双十一和抢票这种流量洪峰的场景下,很容易就会把我们的系统打垮。而作为系统服务的卫兵的网关组件,作为系统服务的统一入口,更需要考虑流量的限制,直接在网关层阻断流量比在各个系统中实现更合适。Spring Cloud Gateway的实现中,就提供了限流的功能,下面主要分析下Spring Cloud Gateway中是如何通过一段lua脚本实现限流功能的。限流的实现方式有多种,下面先回顾下几种常见的实现算法这种限流算法最简单,也是最容易实现的,通过在单位时间内设置最大访问数就可以达到限流的目的。比如某个系统能够承载的一般qps为60,那我们就可以使用计算器法,在单位时间一秒内,限制接口只能被访问60次即可。但是这个算法实现,正如其功能描述一样,有个缺陷,假如在时间窗的前1%的时间内流量就达到顶峰了,那么在时间窗内还有99%的时间系统即使能够继续提供服务,还是会被限流算法的这种缺陷阻断在门外,这种缺陷也被称为“突刺效应“漏桶法不同于计算器法,它有效的避免了计数器法限流的“突刺效应”缺陷,实现也不复杂,通过固定大小的队列+定时取队列元素的方式即可实现。如其名漏桶,就像一个盛水的容器,漏桶法只限制容器出水的速率,当进水的速率过大时,将会填满容器造成溢出,溢出部分的流量也就是拒绝的流量。比如,容器大小为100,出水速率为每秒10/s,当桶为空时,最大的流量可以到达100/s,但是即使这样,受限于固定的流出速率,后端处理的也只能是最大每秒10个,其余的流量都会被缓冲在漏桶中。这个也这是漏桶法的缺陷,没法真正处理突发的流量洪峰,效率不高。令牌桶法也是基于桶的原型,但是和漏桶算法截然不同的时,没有出水口。令牌桶通过令牌的产生速率+令牌桶的容积来控制流量,有效的解决了漏桶效率不高的问题。如,容积为100的桶,令牌产生速率为50/s,那么就代表当桶中令牌已满的时候,最大能够承载100的流量,后面如果流量一直居高不下,也会以每秒50个流量的速度恒速处理请求。令牌桶的这种特性有效的处理了洪峰流量也能做到不被洪峰压垮,是目前限流比较常见的实现方法。比较著名的实现有谷歌guava中的RateLimiter。然后下面将要分析的Spring Cloud Gateway中也是使用的令牌桶算法实现的限流guava的文档:https://github.com/google/guava/wikiSpring网关中是基于令牌桶+redis实现的网关分布式限流,具体的实现见下面两个代码:lua脚本地址:resources/META-INF/scripts/request_rate_limiter.luaRedisRateLimiter:gateway/filter/ratelimit/RedisRateLimiter.java上面博主截取了Spring网关限流部分的关键代码,可以看到,最关键的地方在于,使用reids执行了一段lua脚本,然后通过返回值【0】是否等于1来判断本次流量是否通过,返回值【1】为令牌桶中剩余的令牌数。就上面这段代码没有看到任何令牌桶算法的影子对吧,所有的精华实 香港云主机现都在request_rate_limiter.lua脚本里面,这个脚本最初是由Paul Tarjan分享出来的,源码地址戳我。脚本如下:下面逐行分析下这段脚本。首先解释下,从应用中入参进来的这几个属性的具体含义:tokens_key:当前限流的标识,可以是ip,或者在spring cloud系统中,可以是一个服务的serviceIDtimestamp_key:令牌桶刷新的时间戳,后面会被用来计算当前产生的令牌数rate :令牌生产的速率,如每秒产生50个令牌capacity :令牌桶的容积大小,比如最大100个,那么系统最大可承载100个并发请求now :当前时间戳requested:当前请求的令牌数量,Spring Cloud Gateway中默认是1,也就是当前请求下面是主要逻辑分析:– 计算填满桶需要多长时间
— 得到填满桶的2倍时间作为redis中key时效的时间,避免冗余太多无用的key
— 这里和令牌桶的实现没有太大的关系
— 获取桶中剩余的令牌,如果桶是空的,就将他填满
— 获取当前令牌桶最后的刷新时间,如果为空,则设置为0
— 计算最后一次刷新令牌到当前时间的时间差
— 计算当前令牌数量,这个地方是最关键的地方,通过剩余令牌数 + 时间差内产生的令牌得到当前总令牌数量
— 设置标识allowad接收当前令牌桶中的令牌数是否大于请求的令牌结果
— 设置当前令牌数量
— 如果allowed为true,则将当前令牌数量重置为通中的令牌数 – 请求的令牌数,并且设置allowed_num标识为1
— 将当前令牌数量写回到redis中,并重置令牌桶的最后刷新时间
— 返回当前是否申请到了令牌,以及当前桶中剩余多少令牌关于Spring Cloud Gateway中一段脚本如何实现令牌桶就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

相关推荐: 怎么解决vue cas系统退出失败,再次刷新才能退出的问题

这篇文章主要介绍“怎么解决vue cas系统退出失败,再次刷新才能退出的问题”,在日常操作中,相信很多人在怎么解决vue cas系统退出失败,再次刷新才能退出的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决vue c…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 08/12 13:22
下一篇 08/12 13:22

相关推荐