Skip to content

热点参数限流

louyuting edited this page Oct 14, 2020 · 9 revisions

Overview

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。

Sentinel 通过埋点的形式,在每次 Entry(opts) 的时候携带上需要流控的参数。具体可以参考:api/api.go/#func WithArgs(args ...interface{}) EntryOption 函数

WithArgs 函数携带的是一个参数列表。Sentinel 的热点参数流控的每个规则会对参数列表中某一位置的参数生效(根据热点参数流控规则中的参数列表 ParamIndex 属性来指定生效参数位置)。Sentinel 会为每个规则都创建独立的统计结构,统计结构会缓存对应参数列表的 ParamIndex 的所有值,根据值的统计做流控。

这里举个例子:假设每次 Entry 的时候携带上的参数的类型列表是:[string, int]。现在有一个规则 R1 在 ParamIndex 是 0 的位置生效,规则基于并发数去做控制,限制最高并发是 100。 那么 Entry 的时候携带上的参数列表 ["sentinel", any number],第一个参数出现 "sentinel" 的请求,并发量不超过 100。

热点参数流控规则

Rule 的定义参考:hotspot.Rule

type Rule struct {
	// ID is the unique id
	ID string `json:"id,omitempty"`
	// Resource is the resource name
	Resource string `json:"resource"`
	// MetricType indicates the metric type for checking logic.
	// For Concurrency metric, hotspot module will check the each hot parameter's concurrency,
	//		if concurrency exceeds the Threshold, reject the traffic directly.
	// For QPS metric, hotspot module will check the each hot parameter's QPS,
	//		the ControlBehavior decides the behavior of traffic shaping controller
	MetricType MetricType `json:"metricType"`
	// ControlBehavior indicates the traffic shaping behaviour.
	// ControlBehavior only takes effect when MetricType is QPS
	ControlBehavior ControlBehavior `json:"controlBehavior"`
	// ParamIndex is the index in context arguments slice.
	// if ParamIndex is great than or equals to zero, ParamIndex means the <ParamIndex>-th parameter
	// if ParamIndex is the negative, ParamIndex means the reversed <ParamIndex>-th parameter
	ParamIndex int `json:"paramIndex"`
	// Threshold is the threshold to trigger rejection
	Threshold int64 `json:"threshold"`
	// MaxQueueingTimeMs only takes effect when MetricType is QPS and ControlBehavior is Throttling
	MaxQueueingTimeMs int64 `json:"maxQueueingTimeMs"`
	// BurstCount is the silent count
	// BurstCount only takes effect when MetricType is QPS and ControlBehavior is Reject
	BurstCount int64 `json:"burstCount"`
	// DurationInSec is the time interval in statistic
	// DurationInSec only takes effect when MetricType is QPS
	DurationInSec int64 `json:"durationInSec"`
	// ParamsMaxCapacity is the max capacity of cache statistic
	ParamsMaxCapacity int64 `json:"paramsMaxCapacity"`
	// SpecificItems indicates the special threshold for specific value
	SpecificItems map[interface{}]int64 `json:"specificItems"`
}
属性 说明 是否必填项 默认值
Resource 资源名 必填
MetricType 流控指标类型 (MetricType),支持两种:请求数和并发数 必填
ControlBehavior 流控的效果 (ControlBehavior),仅在请求数模式下有效。支持两种:快速失败和匀速+排队模式 必填
ParamIndex 热点参数的索引,对应 WithArgs(args ...interface{}) 中的参数索引位置,从 0 开始 必填
Threshold 限流阈值(针对每个热点参数) 必填
MaxQueueingTimeMs 最大排队等待时长(仅在匀速排队模式 + QPS 下生效) 选填
BurstCount 静默值(仅在快速失败模式 + QPS 下生效) 选填
DurationInSec 统计结构填充新的 token 的时间间隔 (仅在请求数(QPS)流控模式下生效) 选填
ParamsMaxCapacity 统计结构的容量最大值(Top N) 选填 20000
SpecificItems 特定参数的特殊阈值配置,可以针对指定的参数值单独设置限流阈值,不受前面 Threshold 阈值的限制。 选填

热点参数流控策略

热点参数流控的控制策略由MetricTypeControlBehavior两个字段决定。

MetricType表示热点参数流控的统计metric类型,Sentinel支持两种:请求数(QPS)和并发数(Concurrency)。

  • Concurrency:基于并发数控制热点参数,这种设置下会使用统计结构中当前参数的并发数来执行流控策略。MetricType是Concurrency时候,字段ControlBehavior不会生效,如果当前参数的并发数超过了阈值,那么就拒绝该请求,如果没超过阈值,就通过检查。
  • QPS:基于请求数控制热点参数,基于token bucket记录的数据和字段ControlBehavior的策略执行流控。

ControlBehavior表示热点参数流量控制器的控制行为,Sentinel支持两种控制行为:Reject(拒绝)和Throttling(匀速排队),需要强调的是,ControlBehavior仅仅在MetricType是QPS时候才生效。

  • Reject:表示如果当前统计周期(DurationInSec)内,统计结构内参数的token已经用完了,就直接拒绝,如果没用完就获取token,通过检查。
  • Throttling:表示匀速排队的统计策略。

热点参数流控统计结构

Sentinel 在加载规则时候会将热点参数流控规则转换成热点参数流量控制器,每个流量控制器都有自己独立的统计结构。Sentinel的热点参数流量控制器的独立统计结构是基于token bucket的思想实现的。统计结构缓存了每个埋点参数的三个metric:上次填Token时间、当前统计时间间隔内剩余Token、当前参数的并发数。

流量控制器的统计结构基于LRU的策略,每个规则默认缓存20000个参数的统计数据。

常见场景规则设置

基于并发数控制热点参数:

{
	Resource:          "some-test",
	MetricType:        hotspot.Concurrency,
	ParamIndex:        0,
	Threshold:         100,
	DurationInSec:     1,
},

上面的配置表示:针对资源,some-test,在参数列表中的第一个参数(index是0)进行流控,每次更新token的周期是1秒,并发数阈值是100。对于Concurrency来说,ControlBehavior,MaxQueueingTimeMs,BurstCount这三个字段都是无效字段,均不用设置。

基于请求数控制热点参数

{
	Resource:          "some-test",
	MetricType:        hotspot.QPS,
        ControlBehavior:   hotspot.Reject
	ParamIndex:        1,
	Threshold:         100,
        BurstCount:        5,
	DurationInSec:     1,
},

上面的配置表示:针对资源,some-test,在参数列表中的第二个参数(index是1)进行流控,每次更新token的周期是1秒,统计时间间隔内请求数阈值是100。对于QPS来说,MaxQueueingTimeMs字段是无效字段,不用设置。

这里配置的流控策略是,超过阈值,直接拒绝流量。

Usage Example

可参考 example 代码:https://github.com/alibaba/sentinel-golang/tree/master/example/hotspot_param_flow