Sentinel热点参数如何限流【原理源码】

2020-11-30 10:44:33 浏览数 (1)

前言

热点参数限流通过对请求的第几个参数以及参数值的流量进行统计,超过阈值触发流控的一种方式,例如:售卖的热销产品的抢购场景。

  1. 那如果入参是对象如何限流?例如入参是Product对象
  2. 参数的不一样,那么多参数是如何统计的呢?
  3. 热点参数都支持哪些限流类型?不同限流类型原理是什么?

一、知识点梳理

二、热点参数流程

1.入口代码

负责热点参数限流的插槽为ParamFlowSlot,当达到设置的阈值时抛出ParamFlowException。

2.判断流程

小结:通过获取热点参数索引号(即第几个参数由用户设置),获取参数值;如果入参是对象,那么该对象需要实现ParamFlowArgument接口并重写paramFlowKey方法提供需要热点参数。

3.参数类型

小结:如果热点参数类型为Collection或者Array,对其中的每个元素循环进行校验。

4.限流类型

小结:热点参数限流支持QPS和并发线程数两种类型。其中QPS的限流效果包括匀速限流和直接限流。

三、直接限流

直接限流注解

小结:热点参数直接限流通过简易令牌桶算法来实现的,请求通过时通过比较剩余令牌的数量。有令牌则放行,无令牌触发热点参数限流抛出ParamFlowException。添加令牌的时机选择在两次请求的时间间隔超过时间窗口大小时,计算出这段时间需要给令牌桶添加多少令牌。热点参数的最大令牌数即用户设置的限流阈值与允许突发流量之和。

四、匀速限流

匀速限流注解

小结:热点参数的匀速限流依然使用漏桶原理,需要注意的是匀速限流最大请求QPS依然为1000。获取匀速通过漏桶时的平均时间,通过与两次请求的时间间隔以及排队等待的时间比较来决定触发热点参数限流还是放行。

五、并发控制

1.并发控制判断注解

2.并发线程计算

上面截图@2.2获取当前热点参数的并发线程数,通过参数索引号和参数值获取,该参数有多少线程并发。例如:productId为第一个参数(paramIdx),值为PID00987(value)。

代码语言:javascript复制
// @2.2 获取当前热点参数的并发线程数
long threadCount = getParameterMetric(resourceWrapper).getThreadCount(rule.getParamIdx(), value);
代码语言:javascript复制

下面来看下如何统计热点参数的,由ParameterMetric中的threadCountMap容器来负责统计。

代码语言:javascript复制
private final Map<Integer/*参数索引号*/, CacheMap<Object/*参数值*/, AtomicInteger/*并发线程统计数*/>> threadCountMap = new HashMap<>();

threadCountMap容器初始化

小结:THREAD_COUNT_MAX_CAPACITY为固定值4000,即每个参数索引对应的不同值最多统计4000个。

增加并发线程数

递降并发线程数

作者丨梁勇 来源丨瓜农老梁

0 人点赞