sentinel 简介
sentinel以流量为切入点,从流量控制,熔断降级,系统自适应保护,黑白名单控制,热点参数限流,集群限流,网关限流多个维度来保障服务的稳定性.sentinel主要具有以下功能
1.流量控制
1.1 配置介绍
sentinel通过用户配置的FlowRule进行流量控制,每个资源都可以配置一个或者多个FlowRule,如果配置了多个FlowRule则sentinel会依次遍历所有的FlowRule直到有FlowRule触发限流或者遍历完所有的规则使请求通过.
每一个FlowRule都有一下参数组成,用户可以组合这些元素来达到自己想要的限流效果
-
-
resource
:资源名,即限流规则的作用对象count
: 限流阈值,每秒允许通过的请求的数量grade
: 限流阈值类型(QPS 或并发线程数)limitApp
: 流控针对的调用来源,若为default
则不区分调用来源,可以在调用之前使用ContextUtil.enter(name,origin)指定,启动name为当前context的名称,origin为请求来源strategy
: 调用关系限流策略,直接限流,关联限流和调用链限流,关联限流需要配合refResource使用,即需要配置一个关联的资源controlBehavior
: 流量控制效果(直接拒绝、Warm Up、匀速排队),匀速排队需要- maxQueueingTimeMs:匀速排队限流效果的时候队列的最大长度
- warmUpPeriodSec:warm up 限流效果的时候预热时间.
- refResource:关联资源的名称
-
1.2 基于qps/线程数的流量控制
1.2.1 基于qps的流量控制
当QPS超过用户在FlowRule中设置的阈值的时候,sentinel就会根据用户在FlowRule中的配置采取流控措施,包括直接拒绝,warn up,匀速排队.
直接拒绝
这个是sentinel基于QPS的默认的流控措施,如果当前QPS超过了阈值,则对新到来的请求直接拒绝.
warn up:
即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。当预热完成之后就进行匀速排队的流控措施.
匀速排队:
匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER
)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。并且sentinel的匀速排队不支持QPS超过1000的场景.
1.2.2 基于线程数的流量控制
线程数控制用于保护业务的线程池不会应为慢调用而耗尽.为了避免这种情况发生我们通常使用不同的线程池隔离不同的业务,这种方案虽然隔离性比较好,但是会创建很多线程,线程切换的开销比较大,对于低延迟的调用有较大影响.sentinel的线程数量的控制不负责创建和维护线程池,而是简单的统计当前请求上下文的线程数量,如果超过了阈值就会自动拒绝新到来的请求.
1.3 基于调用关系的流量控制
1.3.1 调用方限流
ContextUtil.enter(resourceName, origin)
方法中的 origin
参数标明了调用方名称。这些信息会在 ClusterBuilderSlot
中被统计.
中的 limitApp
字段用于根据调用方进行流量控制。该字段的值有以下三种选项,分别对应不同的场景:
-
-
default
:表示不区分调用者,来自任何调用者的请求都将进行限流统计。如果这个资源名的调用总和超过了这条规则定义的阈值,则触发限流。{some_origin_name}
:表示针对特定的调用者,只有来自这个调用者的请求才会进行流量控制。例如NodeA
配置了一条针对调用者caller1
的规则,那么当且仅当来自caller1
对NodeA
的请求才会触发流量控制。other
:表示针对除{some_origin_name}
以外的其余调用方的流量进行流量控制。例如,资源NodeA
配置了一条针对调用者caller1
的限流规则,同时又配置了一条调用者为other
的规则,那么任意来自非caller1
对NodeA
的调用,都不能超过other
这条规则定义的阈值。
-
同一个资源名可以配置多条规则,规则的生效顺序为:{some_origin_name} > other > default
注意:调用来源的数目不要太多(一般不要超过几百个),否则内存占用会非常多(调用来源的统计节点最大数目=资源数目*来源数目)。
1.3.2 调用链路入口限流
NodeSelectorSlot
中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root
的虚拟节点,调用链的入口都是这个虚节点的子节点。
一棵典型的调用树如下图所示:
machine-root
/ \
/ \
Entrance1 Entrance2
/ \
/ \
DefaultNode(nodeA) DefaultNode(nodeA)
上图中来自入口 Entrance1
和 Entrance2
的请求都调用到了资源 NodeA
,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 strategy
为 RuleConstant.STRATEGY_CHAIN
,同时设置 refResource
为 Entrance1
来表示只有从入口 Entrance1
的调用才会记录到 NodeA
的限流统计当中,而不关心经 Entrance2
到来的调用。
1.3.3 关联限流
当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说,read_db
和 write_db
这两个资源分别代表数据库读写,我们可以给 read_db
设置限流规则来达到写优先的目的:设置 strategy
为 RuleConstant.STRATEGY_RELATE
同时设置 refResource
为 write_db
。这样当写库操作过于频繁时,读数据的请求会被限流。
2.熔断降级
2.1 参数配置
熔断降级的配置规则在DegradeRule中配置,可以配置一下参数
-
resource
:资源名,即限熔断降级的作用对象grade
: 熔断策略,支持慢调用比例/异常比例/异常数策略count
: 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值timeWindow
: 熔断时长,单位为秒minRequestAmount
: 熔断触发的最小请求数量,少于这个数量则不会触发熔断.- statIntervalMs:统计时长,单位为毫秒,默认为1000ms
- warmUpPeriodSec:warm up 限流效果的时候预热时间.
- slowRatioThreshold:慢调用比例阈值,仅慢调用比例模式有效
2.2 熔断策略
-
- 慢调用比例 (
SLOW_REQUEST_RATIO
)
选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。 - 异常比例 (
ERROR_RATIO
)
当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0, 1.0]
,代表 0% - 100%。 - 异常数 (
ERROR_COUNT
)
当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
- 慢调用比例 (
3.系统自适应保护
Sentinel 系统自适应保护从整体维度对应用入口流量进行控制,结合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
Sentinel 在系统自适应保护的做法是,用 load1 作为启动控制流量的值,而允许通过的流量由处理请求的能力,即请求的响应时间以及当前系统正在处理的请求速率来决定。
3.1 配置介绍
系统自适应保护的规则在SystemRule中配置,可以配置一下参数
-
-
highestSystemLoad:(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的
maxQps * minRt
计算得出。设定参考值一般是CPU cores * 2.5
。 - highestCpuUsage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
- avgRt:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- maxThread:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护
-
4.来源访问控制
有时候我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的黑白名单控制的功能。黑白名单根据资源的请求来源(origin
)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。调用方信息通过 ContextUtil.enter(resourceName, origin)
方法中的 origin
参数传入。
4.1 参数配置
黑白名单规则(AuthorityRule
)非常简单,主要有以下配置项
-
- resource:需要保护的资源名称
- limitApp:访问的来源名称,如果有多个来源则使用逗号分割,eg:appA,appB
- strategy:保护的策略,白名单/黑名单.
AUTHORITY_WHITE
为白名单模式,AUTHORITY_BLACK
为黑名单模式,默认为白名单模式
5.热点参数限流
很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
-
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。要使用热点参数限流功能,需要引入sentinel-parameter-flow-control依赖.
5.1.参数配置
热点参数规则在ParamFlowRule中配置,类似于FlowRule
-
- resource:资源名称,必填.
- count:限流阈值,必填,
- grade :限流模式:QPS或者线程数量.默认为QPS
- durationInSec:统计窗口时间长度,单位为秒.默认1s,
- controlBehavior:流控效果,支持快速失败和匀速排毒.默认为快速失败
- maxQueueingTimeMs:最大排队等待时长,仅在匀速排队模式的时候生效,默认为0ms
- paramIdx:热点参数的索引,必填,即在SphU.entry中掺入的args的索引位置.
- paramFlowItemList:参数例外想,可以只针对指定的参数值打暗渡设置限流阈值,不受上面配置的影响.
- clusterMode:是否是集群参数流控规则.默认为false
- clusterConfig:集群流控香相关配置.
6.集群限流
集群流控还可以解决流量不均匀导致总体限流效果不佳的问题。假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 QPS,理想情况下整个集群的限流阈值就为 100 QPS。不过实际情况下流量到每台机器可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。因此仅靠单机维度去限制的话会无法精确地限制总体流量。而集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果
集群流控中共有两种身份:
-
- Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。
- Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)
Sentinel 引入了集群流控模块,主要包含以下几部分:
-
sentinel-cluster-common-default
: 公共模块,包含公共接口和实体sentinel-cluster-client-default
: 默认集群流控 client 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展sentinel-cluster-server-default
: 默认集群流控 server 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展;同时提供扩展接口对接规则判断的具体实现(TokenService
),默认实现是复用sentinel-core
的相关逻辑
6.1 规则配置
FlowRule
添加了两个字段用于集群限流相关配置:
-
- clusterMode : 是否为集群模式
- ClusterFlowConfig:集群限流模式相关配置
flowId
代表全局唯一的规则 ID,Sentinel 集群限流服务端通过此 ID 来区分各个规则,因此务必保持全局唯一。一般 flowId 由统一的管控端进行分配,或写入至 DB 时生成thresholdType
代表集群限流阈值模式。其中单机均摊模式下配置的阈值等同于单机能够承受的限额,token server 会根据客户端对应的 namespace(默认为project.name
定义的应用名)下的连接数来计算总的阈值(比如独立模式下有 3 个 client 连接到了 token server,然后配的单机均摊阈值为 10,则计算出的集群总量就为 30);而全局模式下配置的阈值等同于整个集群的总阈值。
6.2 客户端配置
在clusterClientConfig中配置
-
serverHost
: token server hostserverPort
: token server 端口requestTimeout
: 请求的超时时间(默认为 20 ms)
6.3 服务端配置
在ClusterServerConfig中配置
-
- namespace set: 集群限流服务端服务的作用域(命名空间),可以设置为自己服务的应用名。集群限流 client 在连接到 token server 后会上报自己的命名空间(默认为
project.name
配置的应用名),token server 会根据上报的命名空间名称统计连接数。 - transport config: 集群限流服务端通信相关配置,如 server port
- flow config: 集群限流服务端限流相关配置,如滑动窗口统计时长、格子数目、最大允许总 QPS等
- namespace set: 集群限流服务端服务的作用域(命名空间),可以设置为自己服务的应用名。集群限流 client 在连接到 token server 后会上报自己的命名空间(默认为
6.4 启动方式
Sentinel 集群限流服务端有两种启动方式:
-
- 独立模式(Alone),即作为独立的 token server 进程启动,独立部署,隔离性好,但是需要额外的部署操作。独立模式适合作为 Global Rate Limiter 给集群提供流控服务。
-
- 嵌入模式(Embedded),即作为内置的 token server 与服务在同一进程中启动。在此模式下,集群中各个实例都是对等的,token server 和 client 可以随时进行转变,因此无需单独部署,灵活性比较好。但是隔离性不佳,需要限制 token server 的总 QPS,防止影响应用本身。嵌入模式适合某个应用集群内部的流控。
sentinel提供了 API 用于在 embedded 模式下转换集群流控身份:http://<ip>:<port>/setClusterMode?mode=<xxx>
其中 mode 为 0
代表 client,1
代表 server,-1
代表关闭。注意应用端需要引入集群限流客户端或服务端的相应依赖。
在独立模式下,我们可以直接创建对应的 ClusterTokenServer
实例并在 main 函数中通过 start
方法启动 Token Server。
7.网关限流
Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:
GatewayFlowRule
:网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。ApiDefinition
:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫my_api
,请求 path 模式为/foo/**
和/baz/**
的都归到my_api
这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。
7.1 参数配置
网关限流规则配置在网关限流规则 GatewayFlowRule中.
-
resource
:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。resourceMode
:规则是针对 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID
)还是用户在 Sentinel 中定义的 API 分组(RESOURCE_MODE_CUSTOM_API_NAME
),默认是 route。grade
:限流指标维度,同限流规则的grade
字段。count
:限流阈值intervalSec
:统计时间窗口,单位是秒,默认是 1 秒。controlBehavior
:流量整形的控制效果,同限流规则的controlBehavior
字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。burst
:应对突发请求时额外允许的请求数目。maxQueueingTimeoutMs
:匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。paramItem
:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。其中的字段:parseStrategy
:从请求中提取参数的策略,目前支持提取来源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP
)、Host(PARAM_PARSE_STRATEGY_HOST
)、任意 Header(PARAM_PARSE_STRATEGY_HEADER
)和任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM
)四种模式。fieldName
:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。pattern
:参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。(1.6.2 版本开始支持)matchStrategy
:参数值的匹配策略,目前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT
)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS
)和正则匹配(PARAM_MATCH_STRATEGY_REGEX
)。(1.6.2 版本开始支持)
用户可以通过 GatewayRuleManager.loadRules(rules)
手动加载网关规则,或通过 GatewayRuleManager.register2Property(property)
注册动态规则源动态推送(推荐方式)。