常用的限流框架

作为应对高并发的手段之一,限流并不是一个新鲜的话题了。从Guava的Ratelimiter到Hystrix,以及Sentinel都可作为限流的工具。

自适应限流

一般的限流常常需要指定一个固定值(qps)作为限流开关的阈值,这个值一是靠经验判断,二是靠通过大量的测试数据得出。但这个阈值,在流量激增、系统自动伸缩或者某某commit了一段有毒代码后就有可能变得不那么合适了。并且一般业务方也不太能够正确评估自己的容量,去设置一个合适的限流阈值。

而此时自适应限流就是解决这样的问题的,限流阈值不需要手动指定,也不需要去预估系统的容量,并且阈值能够随着系统相关指标变化而变化。

自适应限流算法借鉴了TCP拥塞算法,根据各种指标预估限流的阈值,并且不断调整。大致获得的效果如下:

从图上可以看到,首先以一个降低的初始并发值发送请求,同时通过增大限流窗口来探测系统更高的并发性。而一旦延迟增加到一定程度了,又会退回到较小的限流窗口。循环往复持续探测并发极限,从而产生类似锯齿状的时间关系函数。

TCP Vegas

vegas是一种主动调整cwnd的拥塞控制算法,主要是设置两个阈值alpha 和 beta,然后通过计算目标速率和实际速率的差diff,再比较差diff与alpha和beta的关系,对cwnd进行调节。伪代码如下:

diff = cwnd*(1-baseRTT/RTT)  
if (diff set: cwndcwnd = cwnd + 1  
else if (diff >= beta)  
set: cwndcwnd = cwnd - 1  
else  
set: cwndcwnd = cwnd

其中baseRTT指的是测量的最小往返时间,RTT指的是当前测量的往返时间,cwnd指的是当前的TCP窗口大小。通常在tcp中alpha会被设置成2-3,beta会被设置成4-6。这样子,cwnd就保持在了一个平衡的状态。

netflix-concuurency-limits

concuurency-limits是netflix推出的自适应限流组件,借鉴了TCP相关拥塞控制算法,主要是根据请求延时,及其直接影响到的排队长度来进行限流窗口的动态调整。

alpha , beta & threshold

vegas算法实现在了VegasLimit类中。先看一下初始化相关代码:

private int initialLimit = 20;  
       private int maxConcurrency = 1000;  
       private MetricRegistry registry = EmptyMetricRegistry.INSTANCE;  
       private double smoothing = 1.0;        
       private Function alphaFunc = (limit) -> 3 * LOG10.apply(limit.intValue());  
       private Function betaFunc = (limit) -> 6 * LOG10.apply(limit.intValue());  
       private Function thresholdFunc = (limit) -> LOG10.apply(limit.intValue());  
       private Function increaseFunc = (limit) -> limit + LOG10.apply(limit.intValue());  
       private Function decreaseFunc = (limit) -> limit - LOG10.apply(limit.intValue());

这里首先定义了一个初始化值initialLimit为20,以及极大值maxConcurrency1000。其次是三个阈值函数alphaFunc,betaFunc以及thresholdFunc。最后是两个增减函数increaseFunc和decreaseFunc。

函数都是基于当前的并发值limit做运算的。

alphaFunc可类比vegas算法中的alpha,此处的实现是3*log limit。limit值从初始20增加到极大1000时候,相应的alpha从3.9增加到了9。

betaFunc则可类比为vegas算法中的beta,此处的实现是6*log limit。limit值从初始20增加到极大1000时候,相应的alpha从7.8增加到了18。

thresholdFunc算是新增的一个函数,表示一个较为初始的阈值,小于这个值的时候limit会采取激进一些的增量算法。这里的实现是1倍的log limit。mit值从初始20增加到极大1000时候,相应的alpha从1.3增加到了3。

这三个函数值可以认为确定了动态调整函数的四个区间范围。当变量queueSize = limit × (1 − RTTnoLoad/RTTactual)落到这四个区间的时候应用不同的调整函数。

变量queueSize

其中变量为queueSize,计算方法即为limit × (1 − RTTnoLoad/RTTactual),为什么这么计算其实稍加领悟一下即可。

常用的限流框架常用的限流框架

我们把系统处理请求的过程想象为一个水管,到来的请求是往这个水管灌水,当系统处理顺畅的时候,请求不需要排队,直接从水管中穿过,这个请求的RT是最短的,即RTTnoLoad;

反之,当请求堆积的时候,那么处理请求的时间则会变为:排队时间+最短处理时间,即RTTactual = inQueueTime + RTTnoLoad。而显然排队的队列长度为

总排队时间/每个请求的处理时间及queueSize = (limit * inQueueTime) / (inQueueTime + RTTnoLoad) = limit × (1 − RTTnoLoad/RTTactual)。

再举个栗子,因为假设当前延时即为最佳延时,那么自然是不用排队的,即queueSize=0。而假设当前延时为最佳延时的一倍的时候,可以认为处理能力折半,100个流量进来会有一半即50个请求在排队,及queueSize= 100 * (1 − 1/2)=50。

动态调整函数

调整函数中最重要的即增函数与减函数。从初始化的代码中得知,增函数increaseFunc实现为limit+log limit,减函数decreaseFunc实现为limit-log limit,相对来说增减都是比较保守的。

看一下应用动态调整函数的相关代码:

private int updateEstimatedLimit(long rtt, int inflight, boolean didDrop) {  
       final int queueSize = (int) Math.ceil(estimatedLimit * (1 - (double)rtt_noload / rtt));  
       double newLimit;  
       // Treat any drop (i.e timeout) as needing to reduce the limit  
       // 发现错误直接应用减函数decreaseFunc  
       if (didDrop) {  
           newLimit = decreaseFunc.apply(estimatedLimit);  
       // Prevent upward drift if not close to the limit  
       } else if (inflight * 2 return (int)estimatedLimit;  
       } else {  
           int alpha = alphaFunc.apply((int)estimatedLimit);  
           int beta = betaFunc.apply((int)estimatedLimit);  
           int threshold = this.thresholdFunc.apply((int)estimatedLimit);  
           // Aggressive increase when no queuing  
           if (queueSize limit if queue is still manageable  
           } else if (queueSize else if (queueSize > beta) {  
               newLimit = decreaseFunc.apply(estimatedLimit);  
           // We're within he sweet spot so nothing to do              } else {                  return (int)estimatedLimit;              }          }          newLimit = Math.max(1, Math.min(maxLimit, newLimit));          newLimit = (1 - smoothing) * estimatedLimit + smoothing * newLimit;          if ((int)newLimit != (int)estimatedLimit && LOG.isDebugEnabled()) {              LOG.debug("New limit={} minRtt={} ms winRtt={} ms queueSize={}",                      (int)newLimit,                      TimeUnit.NANOSECONDS.toMicros(rtt_noload) / 1000.0,                      TimeUnit.NANOSECONDS.toMicros(rtt) / 1000.0,                      queueSize);          }          estimatedLimit = newLimit;          return (int)estimatedLimit;      } 

动态调整函数规则如下:

当变量queueSize

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/222227.html<

(0)
运维的头像运维
上一篇2025-04-15 09:49
下一篇 2025-04-15 09:51

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

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