目标:Sentinel的基本应用 工具:IDEA--2020.1、Sentinel Maven 学习目标:学习Sentinel的限流设置 本次学习的工程下载链接放到文本最后面
使用Sentinel的核心库来实现限流,主要分为以下几个步骤
- 定义需要限流资源(需要通过限流保护的基本元素--对需要保护的资源设置限流规则)
- 定义限流规则
- 检验限流规则是否生效
1.Sentinel实现限流
首先,引入Sentinel的核心库
代码语言:javascript复制<!--引入Sentinel的核心库-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.2</version>
</dependency>
然后定义一个普通的业务类方法;
代码语言:javascript复制private static void doSomething() {
try (Entry entry = SphU.entry("doSomething")){
//业务逻辑处理
System.out.println("hello world" System.currentTimeMillis());
} catch (BlockException ex){
//被流控处理的逻辑
}
}
在doSomething方法中,通过使用Sentinel中的SphU.entry("doSomething")定义一个资源来实现流控的逻辑,他表示当请求进入doSomething方法时,需要进行限流判断,如果抛出BlockException 异常,则表示出发了限流。
接着,针对该保护的资源定义限流规则;
代码语言:javascript复制private static void initFlowRules(){
ArrayList<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("doSomething");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
针对资源doSomething,通过initFlowRules设置限流规则,其中参数的含义如下。 Grade:限流阈值类型,QPS模式(1)或并发线程数模式(0) count:限流阈值 resource:设置需要保护的资源,这个资源的名称必须和SphU.entry中使用的名称一致
这个代码的意思是,针对doSomething方法,每秒最多允许通过20个请求,也就是QPS为20。
最后通过main方法测试:
代码语言:javascript复制public static void main(String[] args) {
initFlowRules();
while (true) {
doSomething();
}
}
效果如下:
我们需要去到日志文件观看(这个图显示了日志在什么位置):
2020-06-13 12:20:07|1|doSomething,FlowException,default,|484052,0 2020-06-13 12:20:08|1|doSomething,FlowException,default,|580113,0 2020-06-13 12:20:09|1|doSomething,FlowException,default,|547396,0 2020-06-13 12:20:10|1|doSomething,FlowException,default,|585820,0 2020-06-13 12:20:11|1|doSomething,FlowException,default,|569697,0 2020-06-13 12:20:12|1|doSomething,FlowException,default,|541199,0
2.资源定义的方式
我们上面是通过抛出异常的方式来定义一个资源
代码语言:javascript复制private static void doSomething1() {
try (Entry entry = SphU.entry("resourceName")){
//被保护的业务逻辑
} catch (BlockException e){
//被限流
}
}
其中,resource可以定义方法名称、接口名称或者其他唯一标识。 除此之外,我们还可以通过放回布尔值的方式来定义资源;
代码语言:javascript复制private static void doSomething2() {
if (SphO.entry("resourceName")){
try {
//被保护的业务逻辑
} finally {
SphO.exit();
}
}else {
//资源访问被限制
}
}
这种方式中,需要注意资源使用玩后需要调用SphO.exit(),否者会导致异常
Sentinel还可以使用@SentinelResource支持注解方式来定义资源,实现方式如下
代码语言:javascript复制@SentinelResource(value = "resourceName" ,blockHandler = "blockHandlerForString")
public String getName(String id){
//业务逻辑
return " ";
}
public String blockHandlerForString(String id,BlockException e){
//被限流后的处理方法
return " ";
}
3.Sentinel资源保护规则
Sentinel支持多种保护规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则、热点参数规则。 完整的限流规则设置如下:
代码语言:javascript复制private void initFlowQpsRule() {
ArrayList<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rule.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
rule.setClusterMode(false);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
其中,FlowRule部分属性的含义说明如下; limitApp: 是否需要针对调用来源进行限流,默认是default,即不区分嗲用来源。 strategy: 调用关系限流策略——直接、链路、关联。 controlBehavior: 流控行为,包括直接拒绝、排队等候、慢启动模式,默认是直接拒绝。 clusterMode: 是否是集群限流,默认是否。
基于并发数和QPS的流量控制 Sentinel流量控制统计有两种类型,通过grade属性来控制: 1.并发线程数(FLOW_GRADE_THREAD) 2.QPS(FLOW_GRADE_QPS)
并发线程数:并发线程数限流用来保护业务线程不被耗尽--这种可能产生资源竞争的问题 Sentinel并发线程数限流就是统计当前请求的上下文线程数量,如果超出阈值,新的请求就会被拒绝 QPS:表示每秒的查询书,也就是一台服务器每秒能够响应的查询次数。当QPS打到限流的阈值,就会触发这个限流规则。
QPS流量控制行为 当QPS超过阈值时候,就出触发流量控制行为,这种行为是通过controlBehavior来设置的,他包含: 1.直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT) 2.Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP),冷启动 3.匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER) 4.冷启动 匀速排队(RuleConstant.CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER) 直接拒绝: 直接拒绝是默认的流量控制方式,也就是请求流量超过阈值时,直接抛出异常 Warm Up: 这是一种冷启动方式,当流量突然增加的时候,我们希望处理逐步递增,这个就能够实现。 匀速排队 这种方式会严格控制请求通过的时间间隔,也就是让请求以匀速的速度通过。这种可以处理间隔性突发流量。 调用关系流量策略 调用方限流 这个就是根据请求来源进行流量控制,我们需要设置limitApp属性来设置来源心思,他有三个选项。 1.default:表示不区分调用者,也就是任何访问调用者的请求都会进行限流统计 2.{some_origin_name}:设置特定的调用者,只用来自这个的调用者请求才会进行流量统计和控制。 3.other:表示针对除{some_origin_name}外的其他调用者进行流量控制。 由于同一个资源可以配置多条规则,如果多个规则设置的limitApp不一样,name规则的生效规则顺序为:{some_origin_name}-> other->default
4.Sentinel实现服务熔断
Sentinel实现服务熔断操作的配置和限流类似,不同之处在于限流采用的是FlowRule,而熔断中采用的是DegradeRule,配置代码如下:
代码语言:javascript复制private static void initDegradeRule() {
ArrayList<DegradeRule> rules = new ArrayList<>();
DegradeRule degradeRule = new DegradeRule();
degradeRule.setResource("key");
degradeRule.setCount(10);
degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
degradeRule.setTimeWindow(10);
degradeRule.setMinRequestAmount(5);
degradeRule.setRtSlowRequestAmount(5);
rules.add(degradeRule);
DegradeRuleManager.loadRules(rules);
}
其中的属性说明: 1.grade:熔断策略,支持秒级RT、秒级异常比例、分钟级异常数。默认是秒级RT 2.timeWindow:熔断降级的时间窗口,单位为s,也就是触发熔断降级之后多长时间内自动熔断 3.rtSlowRequestAmount:在RT模式下,1s内持续多少个请求的的平均RT超出阈值后触发熔断,默认值为5 4.minRequestAmount:触发的异常熔断最小请求数,请求数小于该值时即使异常比例超出阈值也不会发生熔断,默认值为5 Sentinel提供三种熔断策略,对于不同策略,参数的含义也不一样: 1.平均响应时间(RuleConstant.DEGRADE_GRADE_RT):如果1s内持续进入5个请求对应的平均时间都超过了阈值(count,单位ms),name接下来的时间窗口(timeWindow,单位为s)内,对这个方法的调用都会自动熔断抛出异常
Sentinel默认统计的RT上线为4900ms,如果超出这个阈值都会算作4900ms,如果需要修改,则通过启动参数-Dcsp.sentinel.statistic.max.rt=xxx来配置
2.异常比例(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO):如果每秒的资源数≥minRequestAmount(默认值是5),并且每秒的资源异常总数占总通过量的比列超过阈值count(count的取值是[0.0,1.0],表示0%-100%),则资源将进入降级状态。同样在接下来的timeWindow之类,对这个方法的调用都会自动触发熔断。 3.异常数(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT):当资源最近一分钟的异常数目超过阈值之后,会触发熔断。需要注意的是,如果timeWindow小于60s,则结束熔断状态后任然可能在进入到熔断状态。
下载链接:sentinel-sample.zip