KLimiter自适应限流器

7e9f04534b2b814df85c310d8c067447.gif

随着互联网业务的快速发展,系统架构日益复杂,对下游资源(如数据库)的保护成为系统稳定性的重要环节。传统的限流方式往往依赖于人为设定的固定阈值,难以应对动态变化的业务需求,容易造成资源浪费或系统过载。为此,本文介绍了KLimiter自适应限流器,它可以基于下游资源(如db)水位,对多个不同优先级的上游入口进行自适应调流。

b1076c36bcd42dfe45d2d9efd94ea859.png

背景

通常情况下,我们对下游资源(如db)的保护,是通过对上游接口限流进行的;多个接口的峰值时间点按约定错峰,并给予一定流量限制,可以保护下游资源在安全水位内。

3f642145037c6434608a7e6320d7ec1b.png

这种做法有以下缺点:

  • 随着业务迭代,上游接口接入方越来越多,形形色色的接口也越开越多,这就导致上游接口的峰值时间错中复杂,难以评估;

  • 上游接口的峰值时间有时候是由口头/书面约定而成,没有强制的系统制约,这就导致多个接口峰值可能会出现如下叠加情况,最终让下游资源水位超过安全阈值。

c2e0927832d4d5a2e252b4599d96476a.png

  • 为了避免问题2的出现,多数系统的做法是将上游接口的限流阈值设置得更低或是对下游资源进行扩容,来保障下游水位安全;但是这种做法又会导致下游长期的资源浪费。

所以,本文实现了一种限流工具,能够基于下游资源的水位自适应调节上游接口流量;即保护的是下游资源水位,但是保护的方式是调节影响该资源的上游接口流量。

介绍

KLimiter为了实现上述诉求,并且支持不同入口优先级不同,本文的限流工具有如下能力:

  • 秒级监测多个下游资源的水位;

  • 自适应调节多个入口的流量,将下游资源水位维持在阈值之下;

  • 多个入口可设置不同的优先级,优先降低低优先级的入口流量到一定比例。

概要设计
  限流方案

基于流量比例进行限流,比如另入口流量比例为70%,那么将阻断30%的请求。

  名词解释

名词

解释

例子

限流入口

需要限制流量的入口

如【查询xxx的接口】就是一个限流入口

资源基线

自适应限流需要关注的下游资源实例;基线包含名称和其水位值

如【 xx库】就是一个资源基线,本文用xx库的操作qps来描述其水位值

入口影响的基线

限流入口会影响资源基线

如【xx接口】,会影响到【aa库】【bb库】这两个基线的水位

影响系数

一个基线可能由多个限流入口影响,不同的入口在不同的时刻,对基线影响的占比是不一样的,这个占比进行归一化后叫做影响系数

如【 aa库】会由【xx接口】、【yy接口】等多个入口影响,某个时刻,一次【xx接口】请求对【 aa库】贡献1qps,一次【yy接口】请求对【 aa库】贡献3qps,则【xx接口】影响系数为0.25,【yy接口】影响系数为0.75;这个影响系数在按优先级调流时会用到

流量比例 

本文通过限制入口的流量比例来实现限流,而不是限制一个具体的qps值


入口优先级

本文入口优先级,定义为期望该入口最多能降低到的流量比例


  设计图解
  • 调流原理

9ce6c1f08d8ca196886af41f1242ae07.png

如图,本文自适应限流器会优先保证入口流量高于其设置的优先级阈值,如果该入口不能再降低流量了,会先降低其他优先级更低的入口流量。如step1中,入口3的流量比例降低到优先级阈值就不能再降了,在step2会让入口1和入口2去降低原本应该由入口3降低的流量比例。

如果所有入口的流量比例均到了优先级的阈值:

1b9aae0a19b2250baae17e39bce69266.png

则会进行第二轮调流,第二轮会一视同仁,所有入口一起降。

  • 代码模块

6b09a91bea9fec6a0d5ad963783f321b.png

如图,一个限流入口会影响多个资源基线,一个资源基线也会被多个限流入口影响;自适应限流器有2个后台线程,分别用于统计qps和计算入口的流量比例:

  • qps采集线程:每1s执行一次,遍历所有入口和基线,计算过去1s的qps值;

  • 流量比例调节线程:每5s执行一次,基于6.1算法重新计算所有入口的影响系数,基于6.2、6.3算法重新计算所有入口的流量比例。

13aef34084cbfaf01feaa5bb8f178aa5.png

挑战

1、多个入口需要有限流的优先级,比如入口A最多降到90%流量比例,入口B最多降到70%流量比例,入口C可以降到0;假设基线期望降低10%的流量,理论上A、B、C均降低10%即可,但如果A流量比例已经是90%了,那么原本应该由A降低的这部分流量,需要由其它入口承担降低(其它入口要降低更多的流量),那么其他入口需要降低多少流量呢,这个比例需要怎么折算?

2、要解决1,需要引入影响系数,不同的入口对基线的影响系数是不一样的,假设A系数是0.4,B系数是0.3,C系数是0.3,那么B、C在降低了原本应该降低的10%流量后,基线还需要降低0.4 * 10%的水位;但是不同时间、不同入口的影响系数必然是在变化的,这个系数如何计算呢?

3、影响系数确定后,基线需要降低的流量比例确认后,多个入口在优先级的限制下,最终每个入口需要降低多少流量比例,这个如何计算呢?

本文设计核心即解决以上三个挑战。

9513e56e7a344972f7348a45e606199d.png

详细设计

  限流入口系数求解

对于某个资源基线,我们以如下流程计算其入口在该资源基线下的影响系数。

假设有n个入口099839946ee992ee308d074f5dbef45e.png,共同影响资源基线y,我们可以知道这n个入口的qpsc26c2b5421daa806d9e5b9ebadea69c5.png,以及这个资源基线的水位L,就可以得出以下方程:

24a5a6de4850225de27425398575eeeb.png

由于入口流量都为0的时候,基线水位L也为0,所以 C=0,即得到:

6b4d5e01b44cb6fbe27d97bd2e774ef2.png

其中64e8e02700f3ac8ef454696bacfaa211.png为n个入口的影响系数;可见,要得到这n个影响系数,需要n个这样的方程;

基于历史采样信息,我们可以获得过去的n个时刻446843edd6b6f299750c20e8709371ee.png的qps矩阵:

510e68ec9cd124a670a9ae3c0b519dda.png

令影响系数为:

78c03e675e76eccb402aa78311208898.png

令历史n个时刻的基线水位为:

bc92e6de601a05a3f8efa9c3acfc5d35.png

最终可以得到历史n个时刻的入口qps和水位关系的方程组:

642f92ce1001aff0fac70f9c17a27ade.png

其为n元1次方程组,基于LU分解法(高斯消元法复杂度02b9a13f5fb4afbda82ab799fb5228f0.png,LU分解法复杂度74637dcf212dfce9524bda61a49d2b0b.png, 故选择LU分解法求解)即可求出c9e49ad1860d21eb04811440b9a5387a.png,最终对它们进行归一化,这里的归一化并非向量的归一化,而是最终描述各个入口占所有入口对基线的影响比例:

691dd3a116f5699349c915cfb41f3ce8.png

上述方法即可得出最终的影响系数;

由于LU分解本质是高斯消元法,需要矩阵A正定,否则无解;另外为负数的解也是没有实际意义的,所以需要讨论劣化场景。

当矩阵非正定,或求出的解为负数时,方程是无解或解是无意义的,此时可以将问题转换为优化问题,令

bd95e114bb15f2546a0b29a9747f62b3.png

由于8d56ebba45e6e969b658732420c3dcd9.png是单调的,所以可以用牛顿迭代法(Newton-Raphson)求最接近初始值近似,第k次迭代结果为:

ffd3be818b6ab5a840f4ed01bae8eab9.png

这里bd18207e63780226b31b09c8272a3e22.png用于控制e21820938066e5b6cff95af0431150ef.png均大于0,若无法满足,则停止迭代;

迭代初始值的选取为上一轮流量调控计算的系数结果,即让本次优化结果更接近于上一轮计算值。为了减少0值的影响,上一轮计算结果为0的,本轮初始值赋1。

  流量降低算法

本文对入口定义的优先级,为期望该入口最多能降低到的流量比例。

令基线当前水位为861594ffa85f3b9e633c294d71564f45.png,期望的阈值水位为3f83555513ff2cebffb45cb0fef215a0.png,则可以得到基线需要降低流量比例为:

2da4483b90048ff64455729c4a7c1e70.png

令当前n个入口bf827f95de8e3a8281e62e9f906e89ed.png的流量比例为ee1a90b9145e256b2975fe44a6231f44.png,假设不降低流量的qps为7a121cf27df30a4eb612181959b30690.png,系数为c957e22feff0b57194dc3bc792be3b60.png,即有

ef444694c8150c7535ec402154445557.png

基线水位降低比例1ca2c0c89e219e728006f16dcd06527f.png,则最终期望的基线水位为06c6249bb085d19c4a844bb9f63179d9.png,即有

0442cd47f50660daeaae2d8b13b0fd59.png

于是有入口3981d15878c1abf31ecd5a13e9cad1ae.png的期望流量比例682d414f83fea6e74ead39f3674cf7e2.png

066bf5f812871f94ed0967e474649aa1.png

即需要降低的流量比例8761a346c2cc4b38feb2075eafaae0e8.png

41302f770437b1d2e46a96410344c39d.png

假设入口fefa3a5bd778eac7e22ebbb56c57a4d4.png当前最多只能降低0ea4b2995b77b8010bda4ccbeb92489a.png的流量比例,那么我们可以认为原本应该由a_i降低的流量比例:

a76f778411ab646aaab8206d47f74fa7.png

需要在下一轮的流量降低调整中,由其他入口进行调整;下一轮的流量调整中,基线还需要降低的流量比例为:

821cda4e8c37068f4f1e4b7d2e973fe7.png

简单描述这个公式,即原本应该由55a20ada298c553a363f1aeccde28123.png降低的流量比例在其当前流量比例的占比,再乘上当前入口在所有入口中的影响比例,得到这次原本应该由cbf3b2909ee741b2283a8a0e0f0ee554.png降低的流量比例对基线水位比例的影响,这部分流量调整在下一轮中由其他入口承担。

  流量提高算法

流量提高是站在入口视角来看的,入口的其中一个基线可以提升的倍数为62d247b60664ed06f0ac230ca25b60da.png,那么这个基线允许入口增加的流量比例为

21769616e26d66c06fa3f44fbf431747.png

一个入口影响的基线可能有多个,最终选取能够提升得最小的一个值。

  一些兜底策略
  • 跌零保护

流量跌0有很多问题,比如方程求解不稳定/不准确,所以流量比例最低只会到1%,当qps小于5,也不再会降低流量比例。

  • 降低流量速率

为了减少计算抖动的影响以及流量比例变化过大的影响,流量比例每次最多调低5%。

  • 慢启动

为了减少计算抖动的影响以及流量比例变化过大,流量的恢复是类似于TCP拥塞控制算法中的慢启动;当流量比例很小的时候,流量调高的比例只允许很小,流量比例越高,允许调高的比例则越高。

12e87b2489b8ed34afeb73fbdf1970f2.png

  • 波动影响

为了减少流量和基线水位抖动对计算的影响,计算所使用的qps、水位,均是用一次计算调流周期做的简单平均滤波(当前计算调流周期为5s,所有的qps、水位值,都是历史5s的平均值)。

a333abfd08e8b8e74bfda34e1d9fcb9f.png

效果

ob基线水位阈值设置为60,入口1优先级为0%,入口2优先级为50%;可见入口2比例到50%后不再降低,只降低入口1;入口1降到0依然不满足,最终入口2也降低到30%左右,保持ob基线水位在60左右。

15e9c183afffee82f341218477975ee3.png

ob基线阈值回调到100,可见入口流量比例也回升,保持ob基线水位在100左右。

f5e64c3ee9732f464c18632adb8914c3.png

结语

KLimiter自适应限流器通过动态监测下游资源的水位,并根据多个入口的不同优先级自适应地调整流量,有效解决了传统限流方式中难以精确控制下游资源水位的问题。相比现有的自适应限流工具,KLimiter不仅能够感知下游资源的实际状态,还能够在多个入口之间灵活分配流量,确保高优先级的服务得到更好的保障。此外,KLimiter通过一系列的优化算法和兜底策略,确保了限流过程的稳定性和可靠性。无论是应对突发流量高峰,还是日常的流量管理,KLimiter都能提供强大的支持,为系统的稳定运行保驾护航。

74dad84887eb2e2f84d3759aa2b9ccfd.png

参考资料

  • 《奇异矩阵定义》:

    https://zhuanlan.zhihu.com/p/662240649

  • 《LU分解解线性方程组》:

    https://zhuanlan.zhihu.com/p/386954541

  • 《高斯消元解线性方程组》:

    https://wuli.wiki/online/GAUSS.html

  • 《浅说 Newton-Raphson 方法》

    https://zhuanlan.zhihu.com/p/696670386

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值