-
Notifications
You must be signed in to change notification settings - Fork 22
热点参数流控
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
Sentinel 通过埋点的形式,在每次使用 EntryBuilder
构建 Entry 的时候通过 with_args
或 with_attachments
方法携带上需要流控的参数。目前仅支持 String 类型的热点字段。
with_args
函数携带的是一个参数列表。Sentinel 的热点参数流控的每个规则会对参数列表中某一位置的参数生效。根据热点参数流控规则中的参数列表 param_index
属性来指定生效参数位置。Sentinel 会为每个规则都创建独立的统计结构,统计结构会缓存对应参数列表的 param_index
的所有值,根据值的统计做流控。类似得,with_attachments
和 param_key
是优先级更高的键值形式的热点参数添加方式。
这里举个例子:假设创建 Entry 的时候携带上的参数的类型列表是:["first_point", "sencond_point"]
。现在有一个规则在 param_index
是 0
的位置生效,规则基于并发数去做控制,限制最高并发是 100。 那么携带的第一个参数是 "first_point" 的请求的 Entry,并发量不得超过 100。
并发隔离规则的定义如下:
pub struct Rule {
pub id: String,
pub resource: String,
pub metric_type: MetricType,
pub control_strategy: ControlStrategy,
pub param_index: isize,
pub param_key: String,
pub threshold: u64,
pub max_queueing_time_ms: u64,
pub burst_count: u64,
pub duration_in_sec: u64,
pub params_max_capacity: usize,
pub specific_items: HashMap<ParamKey, u64>,
}
一条流控规则主要由下面的参数组成,我们可以组合这些元素来实现不同的限流效果:
-
id
:规则的唯一标识,使用 API 加载规则时,可省略,默认为随机的 uuid;使用标签宏加载规则时,默认为资源名(同时,标签宏仅支持单一规则)。 -
resource
:资源名,即规则的作用目标。 -
metric_type
:流控指标类型,支持两种:请求数MetricType::QPS
和并发数MetricType::Concurrency
。 -
control_strategy
: 表示流量控制器的控制策略,是一个ControlStrategy
类型的枚举变量。Reject
表示超过阈值直接拒绝,Throttling
表示匀速排队。 -
param_key
、param_index
从构造 Entry 的参数中取热点字段,前者优先级更高,目前仅支持 String 类型热点字段。 -
threshold
: 针对某个热点的阈值。 -
max_queueing_time_ms
: 匀速排队的最大等待时间,该字段仅在 QPS 指标下,控制策略为ControlStrategy::Throttling
时生效。 -
burst_count
:静默值,该字段仅在 QPS 指标下,快速失败模式(即ControlStrategy::Direct
时)生效。 -
duration_in_sec
:统计结构填充新的 token 的时间间隔,该字段仅在请求数 (QPS) 流控模式下生效。 -
params_max_capacity
:统计结构的容量最大值(Top N),默认为 20000。 -
specific_items
: 特定参数的特殊阈值配置,可以针对指定的参数值单独设置限流阈值,不受前面threshold
阈值的限制。
热点参数流控的控制策略由 MetricType
和 ControlBehavior
两个字段决定。
MetricType
表示热点参数流控的统计指标类型,Sentinel支持两种:请求数 (QPS) 和并发数 (Concurrency)。
-
Concurrency
:基于并发数控制热点参数,这种设置下会使用统计结构中当前参数的并发数来执行流控策略。MetricType
是Concurrency
的时候,字段ControlBehavior
不会生效,如果当前参数的并发数超过了阈值,那么就拒绝该请求,如果没超过阈值,就通过检查。 -
QPS
:基于请求数控制热点参数,基于令牌桶记录的数据和字段ControlBehavior
的策略执行流控。
ControlBehavior
表示热点参数流量控制器的控制行为,Sentinel 支持两种控制行为:Reject (快速失败) 和 Throttling (匀速排队),需要强调的是,ControlBehavior
仅仅在 MetricType
是 QPS 时候才生效。
- Reject:表示如果当前统计周期 (
DurationInSec
) 内,统计结构内参数的 token 已经用完了,就直接拒绝,如果没用完就获取token,通过检查。 - Throttling:表示匀速排队的统计策略。
Sentinel 在加载规则时候会将热点参数流控规则转换成热点参数流量控制器,每个流量控制器都有自己独立的统计结构。Sentinel 的热点参数流量控制器的独立统计结构是基于令牌桶的思想实现的。统计结构缓存了每个埋点参数的三个指标:上次填 Token 时间、当前统计时间间隔内剩余 Token、当前参数的并发数。
流量控制器的统计结构基于LRU的策略,每个规则默认缓存 20000 个参数的统计数据。
{
resource: "some-test".into(),
metric_type: MetricType::Concurrency,
param_index: 0,
threshold: 100,
duration_in_sec: 1,
..Default::default()
},
上面的配置表示:针对资源,some-test,在参数列表中的第一个参数 (index 是 0) 进行流控,每次更新 token 的周期是 1 秒,并发数阈值是 100。对于 Concurrency 来说,control_strategy
, max_queueing_time_ms
, burst_count
这三个字段都是无效字段,均不用设置。
{
resource: "some-test".into(),
metric_type: MetricType::QPS,
control_strategy: ControlStrategy::Reject,
param_index: 1,
threshold: 100,
burst_count: 5,
duration_in_sec: 1,
..Default::default()
},
上面的配置表示:针对资源,some-test,在参数列表中的第二个参数 (index是1) 进行流控。这里配置的流控策略是,超过阈值,直接拒绝流量。每次更新 token 的周期是1秒,统计时间间隔内请求数阈值是 100。对于快速失败 (Reject
) 的控制策略来说,max_queueing_time_ms
字段是无效字段,不用设置。