何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
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 阈值的限制。 | 选填 | 无 |
热点参数流控的控制策略由MetricType
和ControlBehavior
两个字段决定。
MetricType
表示热点参数流控的统计metric类型,Sentinel支持两种:请求数(QPS)和并发数(Concurrency)。
MetricType
是Concurrency时候,字段ControlBehavior
不会生效,如果当前参数的并发数超过了阈值,那么就拒绝该请求,如果没超过阈值,就通过检查。ControlBehavior
的策略执行流控。ControlBehavior
表示热点参数流量控制器的控制行为,Sentinel支持两种控制行为:Reject(拒绝)和Throttling(匀速排队),需要强调的是,ControlBehavior
仅仅在MetricType
是QPS时候才生效。
DurationInSec
)内,统计结构内参数的token已经用完了,就直接拒绝,如果没用完就获取token,通过检查。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
字段是无效字段,不用设置。
这里配置的流控策略是,超过阈值,直接拒绝流量。
可参考 example 代码:https://github.com/alibaba/sentinel-golang/tree/master/example/hotspot_param_flow