Sentinel - 【基本概念、规则与资源】
官方文档:https://github.com/alibaba/Sentinel/wiki
一、Sentinel介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。
1. Sentinel的两个基本概念
资源: 可以是Java应用程序中的任何内容,可以是应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码,只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名。
规则: 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
使用 Sentinel 来进行资源保护,主要分为三步:
- 定义资源
- 定义规则
- 检验规则是否生效
2. Sentinel的功能
2.1 流量控制规则(FlowRule)
流量控制用于调整网络包的发送数据。任意时间到来的请求往往是随机不可控的,比如商品大促,由于系统处理能力是有限的。所以需要Sentinel作为一个调配器,对流量进行控制。
流量控制有以下几个角度:
-
资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
-
运行指标,例如 QPS、线程池、系统负载等;
-
控制的效果,例如直接限流、冷启动、排队等。
QPS: 每秒查询率,表示计算机中服务器每秒钟查询的次数
Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。
2.2 熔断降级规则(DegradeRule)
当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。这个和Hystrix的原则是一致的。
2.3 系统保护规则(SystemRule)
当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应;在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。针对这些情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
2.4 访问控制规则(AuthorityRule)
很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。黑白名单根据资源的请求来源限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
2.5 热点规则(ParamFlowRule)
这里的热点指的是经常访问的数据,热点规则就是通过统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。
二、规则与资源的定义
1. 规则的定义
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。Sentinel 支持以下几种规则:
- 流量控制规则(FlowRule)
- 熔断降级规则(DegradeRule)
- 系统保护规则(SystemRule)
- 来源访问控制规则(AuthorityRule)
- 热点参数规则(ParamFlowRule)
这些规则在定义的时候都是大同小异的。
1.1 流量控制规则
同一个资源可以同时有多个限流规则,检查规则时会依次检查,通过FlowRuleManager.loadRules(FlowRule集合)
加载新流量控制规则(之前的规则将被替换)。FlowRule 包含以下重要属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
count | 流量控制阈值计数 | |
grade | 流控制的阈值类型(0:线程数,1:QPS) | QPS 模式 |
limitApp | 流控针对的调用来源 | default ,代表不区分调用来源 |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 速率限制器控制行为。 0.默认(直接拒绝),1.预热,2.限速器,3.预热+限速器 | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private void initFlowRules() { //流控规则 List<FlowRule> rules = new ArrayList<>(); //流控 FlowRule flowRule = new FlowRule(); //设置流控的资源 flowRule.setResource("资源名"); //设置流控规则-QPS flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); //设置受保护资源阈值-每秒只能访问一次 flowRule.setCount(1); rules.add(flowRule); //加载配置好的规则 FlowRuleManager.loadRules(rules); }
- 当流控规则为设为QPS,且阈值为1时,表示每秒钟只能对一个请求进行处理,其他的都会被流控。
- 当流控规则为设为线程数,且阈值为1时,表示只同时处理一个请求,也就是第一个进来的请求再未做出响应时,其他再进来的请求都会被流控。
1.2 熔断降级规则
同一个资源可以同时有多个降级规则,通过DegradeRuleManager.loadRules(DegradeRule集合)
加载新的降级规则(之前的规则将被替换)。DegradeRule 包含以下重要属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,降级规则的作用对象 | |
grade | 熔断策略(0:平均RT,1:异常比率,2:异常计数) | 按平均响应耗时 |
count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用,单位ms);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为 s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21private void initDegradeRule() { List<DegradeRule> rules = new ArrayList<>(); DegradeRule degradeRule = new DegradeRule(); //设置熔断降级资源名 degradeRule.setResource("资源名"); //设置降级规则-异常数 degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); //阈值计数,这里是触发熔断异常数- 2+1 degradeRule.setCount(2); //可以触发熔断的最小请求数(在活动统计时间跨度内)-2 degradeRule.setMinRequestAmount(2); //统计时间间隔,单位ms -1分钟 degradeRule.setStatIntervalMs(60*1000); //熔断器打开时的恢复超时(以秒为单位)。超时后,断路器将转换为半开状态以尝试一些请求 degradeRule.setTimeWindow(10); rules.add(degradeRule); //加载配置好的规则 DegradeRuleManager.loadRules(rules); //上述意思是在一分钟内,请求数超过2次,并且当异常数大于2(第三次也算入异常,第四次才熔断),之后请求会被熔断;10s后断路器转换为半开状态,当再次请求又异常时,下次会直接被熔断,之后重复(10s-半开-请求)。 }
1.3 系统保护规则
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。通过 调用SystemRuleManager.loadRules(SystemRule集合)
来硬编码的方式定义流量控制规则。SystemRule包含以下重要属性:
属性 | 说明 | 默认值 |
---|---|---|
highestSystemLoad | load1 触发值,用于触发自适应控制阶段 | -1 (不生效) |
highestCpuUsage | CPU 使用率超过阈值即触发系统保(0.0-1.0) | -1 (不生效) |
avgRt | 当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护(ms) | -1 (不生效) |
maxThread | 当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护 | -1 (不生效) |
qps | 当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护 | -1 (不生效) |
1
2
3
4
5
6
7
8private void initSystemRule() { List<SystemRule> rules = new ArrayList<>(); SystemRule rule = new SystemRule(); rule.setHighestSystemLoad(10); rules.add(rule); SystemRuleManager.loadRules(rules); }
1.4 访问控制规则
也是授权规则,也叫黑名单规则,通过AuthorityRuleManager.loadRules(AuthorityRule集合)
加载规则,有以下重要属性:
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名 | |
limitApp | 对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB | |
strategy | 限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式 | 白名单模式 |
1
2
3
4
5
6
7
8private void initAuthorityRule() { AuthorityRule rule = new AuthorityRule(); rule.setResource("test"); rule.setStrategy(RuleConstant.AUTHORITY_WHITE); rule.setLimitApp("appA,appB"); AuthorityRuleManager.loadRules(Collections.singletonList(rule)); }
1.5 热点规则
热点参数规则(ParamFlowRule
)类似于流量控制规则(FlowRule
):
属性 | 说明 | 默认值 |
---|---|---|
resource | 资源名,必填 | |
count | 限流阈值,必填 | |
grade | 限流模式 | QPS 模式 |
durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s |
controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 | 快速失败 |
maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 | 0ms |
paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 | |
paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型 | |
clusterMode | 是否是集群参数流控规则 | false |
clusterConfig | 集群流控相关配置 |
1
2
3
4
5
6
7
8
9
10ParamFlowRule rule = new ParamFlowRule(resourceName) .setParamIdx(0) .setCount(5); // 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5. ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B)) .setClassType(int.class.getName()) .setCount(10); rule.setParamFlowItemList(Collections.singletonList(item)); ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
2. 资源定义
2.1 抛异常的方式定义资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Entry entry = null; try { //指定针对的资源名,该资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。 entry = SphU.entry("资源名"); //被保护的业务逻辑 do something... } catch (BlockException e) { //资源访问阻止,被限流或被降级 //进行相应处理操作 } catch (Exception e) { //若需要配置降级规则,需要通过这种方式记录业务异常 Tracer.traceEntry(e,entry); } finally { //务必保证 exit,务必保证每个 entry 与 exit 配对 if (entry != null) { entry.exit(); } }
SphU.entry(String name, EntryType trafficType, int batchCount, Object... args)
的参数描述:name – 受保护资源的唯一名称;
trafficType – 资源调用的流量类型,是入口流量(EntryType.IN
)还是出口流量(EntryType.OUT
),只有SystemRule(系统保护规则)对IN生效;
batchCount – 本次资源调用请求的 token 数目
args – 传入的参数,用于热点参数限流
2.2 返回布尔值方式定义资源
SphO
提供 if-else 风格的 API。用这种方式,当资源发生了限流之后会返回 false
,这个时候可以根据返回值,进行限流之后的逻辑处理。示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 资源名可使用任意有业务语义的字符串 if (SphO.entry("自定义资源名")) { // 务必保证finally会被执行 try { /** * 被保护的业务逻辑 */ } finally { SphO.exit(); } } else { // 资源访问阻止,被限流或被降级 // 进行相应的处理操作 }
2.3 注解的方式定义资源
@SentinelResource 注解详解:
-
value: 资源名
-
entryType: 默认EntryType.OUT
-
blockHandler/blockHandlerClass: 对应处理 BlockException 异常的函数名称与该函数所在类的class对象。该函数返回类型必须和原方法一致,且参数列表一致的情况下还必须多一个BlockException类型的参数。在同一类中时,blockHandlerClass可省略,指定函数必须是
public
;当该函数在别的类中时,blockHandlerClass指定所在类的class对象并且函数必须时public static
修饰。 -
fallback/fallbackClass: 指在抛出异常的时处理的函数名与该函数所在类的class对象。该函数返回类型必须和原方法一致,且参数列表一致的情况下还可以多一个Throwable 类型的参数用于接收对应的异常。在同一类中时,fallbackClass可省略,指定函数必须是
public
;当该函数在别的类中时,fallbackClass指定所在类的class对象并且函数必须时public static
修饰。 -
defaultFallback: 默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
- defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
-
exceptionsToIgnore: 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@SentinelResource(value = "资源名",blockHandler = "testHandler",fallback = "testFallback") public String test() { if (Math.random()>0.7) { throw new RuntimeException("抛出运行异常"); } return "str"; } public String testHandler(BlockException be) { be.printStackTrace(); return "被流控了"; } public String testFallback(Throwable e) { e.printStackTrace(); return "抛出异常"; }
最后
以上就是兴奋春天最近收集整理的关于Sentinel - 【基本概念、规则与资源】Sentinel - 【基本概念、规则与资源】的全部内容,更多相关Sentinel内容请搜索靠谱客的其他文章。
发表评论 取消回复