Sentinel流量控制
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Sentinel流量控制
⼀、Sentinel 介绍
Sentinel 是阿⾥巴巴出品的⾯向分布式服务架构的轻量级流量控制组件,主要以流量为切⼊点,从限流,流量整形、熔断降级、系统负载保护等多个维度来保障微服务的稳定性。
Sentinel Hystrix resilience4j
隔离策略信号量隔离(并发线程隔离)线程池隔离/信号量隔
离
信号量隔离
熔断降级策略基于响应时间、异常⽐率、异常数基于异常⽐率基于异常⽐率、响应时间实时统计实现滑动窗⼝滑动窗⼝Ring Bit Buffer
动态规则配置⽀持多种数据源⽀持多种数据源有限⽀持
扩展性多个扩展点插件的形式接⼝的形式
基于注解的⽀
持
⽀持⽀持⽀持
限流基于 QPS,⽀持基于调⽤关系的限流,线程数限流等有限的⽀持Rate Limiter
流量整形基于预热模式、匀速器模式、预热排队模式不⽀持简单的 Rate Limiter模式系统⾃适应保
护
⽀持不⽀持不⽀持
控制台提供开箱即⽤的控制台,可配置规则,查看秒级监控,机器发
现等
简单的监控查看
不提供控制台,可对接其它监控系
统。
1、Sentinel 组成
Sentinel 的使⽤主要分为两个部分:
【1】核⼼库:主要指 Java客户端,不依赖任何框架/库,能够运⾏在 Java7及以上版本的运⾏时环境,同时对 Dubbo/SpringCloud 等框架也有较好的⽀持。
【2】控制台:控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。
2、Sentinel 的特性
3、Sentinel 的相关概念
【1】资源:资源是 Sentinel 的关键概念。
它可以是 Java 应⽤程序中的任何内容,例如,由应⽤程序提供的服务,或由应⽤程序调⽤的其它应⽤提供的服务,甚⾄可以是⼀段代码。
在接下来的⽂档中,我们都会⽤资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。
⼤部分情况下,可以使⽤⽅法签名,URL,甚⾄服务名称作为资源名来表⽰资源。
【2】规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。
所有规则可以动态实时调整。
⼆、Sentinel 流控降级⼊门
Sentinel 本地应⽤流控降级实现分为三步:
【创建本地应⽤】【1】pom.xml 中引⼊ sentinel-core 依赖
1<dependency>
2<groupId>com.alibaba.csp</groupId>
3<artifactId>sentinel-core</artifactId>
4<version>1.7.2</version>
5</dependency>
创建 Sentinel 限流规则⽅案⼆ [不建议使⽤](在应⽤中使⽤代码编写流控规则)
1package com.zzx.sentinelquickstart.controller;
2
3import com.alibaba.csp.sentinel.Entry;
4import com.alibaba.csp.sentinel.SphU;
5import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
7import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
8import org.springframework.web.bind.annotation.GetMapping;
9import org.springframework.web.bind.annotation.RestController;
10
11import javax.annotation.PostConstruct;
12import java.util.ArrayList;
13import java.util.List;
14
15/**
16 * @description::sentinel 测试类
17 * @author: zzx
18 * @createDate: 2020/9/26
19 * @version: 1.0
20*/
21 @RestController
22public class TestController {
23
24 @GetMapping("/hello")
25public String hello(){
26//使⽤限流规则
27try(Entry entry = SphU.entry("Hello")) {//限流⼊⼝
28//被保护的规则
29return "hello Sentinel";
30 }catch (Exception e){
31 e.printStackTrace();
32return "系统繁忙,请稍等";
33 }
34 }
35
36/**
37 * @Description 定义限流规则
38 * @Author zhengzhaoxiang
39 * @Date 2020/9/26 8:58
40 * @Param
41 * @Return
42*/
43 @PostConstruct //当前类的构造函数执⾏之后执⾏
44public void initFlowRules(){
45//1、创建存放限流规则的集合,存放 FlowRule
46 List<FlowRule> flowRules = new ArrayList<>();
47//2、创建限流规则
48 FlowRule flowRule = new FlowRule();
49 flowRule.setResource("Hello");//定义资源,表⽰ sentinel 会对哪个资源⽣效
50 flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//定义限流规则的类型 = QPS
51 flowRule.setCount(2);// 定义 QPS 秒能通过的请求个数
52//3、将限流规则放到集合中
53 flowRules.add(flowRule);
54//4、加载限流规则
55 FlowRuleManager.loadRules(flowRules);
56 }
57 }
搭建本地 Sentinel 控制台:Sentinel 提供⼀个轻量级的开源控制台,它提供机器发现以及健康情况管理、实时监控(单机和集群),规则管理和推送的功能。
本地控制台搭建步骤:
【1】下载 Sentinel 控制台 jar包:
【2】启动 Sentinel 控制台:jdk1.8及以上,使⽤如下命令启动控制台:9000是端⼝;
java -Dserver.port=9000 -jar sentinel-dashboard-1.7.2.jar
本地应⽤接⼊本地 Sentinel控制台:本地应⽤是以客户端的⾝份来接⼊控制台,具体步骤如下:
【1】在本地应⽤的 pom.xml⽂件中引⼊依赖:
1<dependency>
2<groupId>com.alibaba.csp</groupId>
3<artifactId>sentinel-transport-simple-http</artifactId>
4<version>1.7.2</version>
5</dependency>
【2】在本地应⽤的 JVM中添加如下启动参数:
1 # dashboard 设置 Sentinel控制台的主机地址和端⼝。
设置本地在 Sentinel 控制台中的名称
2 -Dcsp.sentinel.dashboard.server=localhost:9000 =SentinelQuickStart
1、Sentinel 定义资源的⽅式
抛出异常的⽅式定义资源 [了解]:Sentinel中的 SphU包含了 try-catch风格的 API。
⽤这种⽅式,当资源发⽣了限流会抛出BlockException。
这个时候可以捕获异常,进⾏限流之后的逻辑处理。
关键代码如下:
1//使⽤限流规则
2try(Entry entry = SphU.entry("Hello")) {//限流⼊⼝
3//被保护的规则
4return "hello Sentinel";
5 }catch (Exception e){
6 e.printStackTrace();
7return "系统繁忙,请稍等";
8 }
返回布尔值⽅式定义资源 [了解]:Sentinel中的 SphO 提供 if-else风格的API。
⽤这种⽅式,当资源发⽣了限流之后就返回 false,这个时候可以根据返回值,进⾏限流之后的逻辑处理。
【1】在 Sentinel_quick_start 项⽬中创建 TestBooleanController使⽤返回布尔值的⽅式定义资源。
需要注意的是 SphO.entry(x)需要与SphO.exit()⽅法成对出现,否则会导致调⽤链记录异常,抛出 ErrorEntryFreeException 异常。
1package com.zzx.sentinelquickstart.controller;
2
3import com.alibaba.csp.sentinel.SphO;
4import org.springframework.web.bind.annotation.GetMapping;
5import org.springframework.web.bind.annotation.RestController;
6
7/**
8 * @description::sentinel 测试类
9 * @author: zzx
10 * @createDate: 2020/9/26
11 * @version: 1.0
12*/
13 @RestController
14public class TestBooleanController {
15
16 @GetMapping("/boolean")
17public Boolean hello(){
18//使⽤限流规则
19if(SphO.entry("Sentinel_Boolean")) {//限流⼊⼝
20try {
21//被保护的资源
22 System.out.println("被保护的资源");
23return true;
24 } finally {
25 SphO.exit();
26 }
27 }else{
28//被限流或降级的处理
29 System.out.println("被限流或降级的处理");
30return false;
31 }
32 }
33 }
异步调⽤⽀持 [了解]:Sentinel ⽀持异步调⽤链路的统计。
在异步调⽤中,需要通过 SphU.asyncEntry(x)⽅法定义资源,并通常需要在异步的回调函数中调⽤ exit⽅法。
【1】在本地应⽤的引导类中添加 @EnableAsync,表⽰ springboot项⽬开始异步调⽤⽀持;
1 @SpringBootApplication
2 @EnableAsync//开启异步调⽤的⽀持
3public class SentinelQuickStartApplication {
4public static void main(String[] args) {
5 SpringApplication.run(SentinelQuickStartApplication.class, args);
6 }
7 }
【2】创建 AsyncService 编写异步调⽤⽅法;
1import org.springframework.scheduling.annotation.Async;
2import org.springframework.stereotype.Service;
3
4/**
5 * @description: 异步⽅法服务类
6 * @author: zzx
7 * @createDate: 2020/9/27
8 * @version: 1.0
9*/
10 @Service
11public class AsyncService {
12
13 @Async //表⽰⽅法是异步调⽤⽅法
14public void hello() throws InterruptedException {
15 System.out.println("异步的开始");
16 Thread.sleep(5000);
17 System.out.println("异步的结束");
18 }
19 }
【3】创建 TestAsyncController,实现异步调⽤限流控制;
1import com.alibaba.csp.sentinel.AsyncEntry;
2import com.alibaba.csp.sentinel.SphO;
3import com.alibaba.csp.sentinel.SphU;
4import com.alibaba.csp.sentinel.slots.block.BlockException;
5import com.zzx.sentinelquickstart.server.AsyncService;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.web.bind.annotation.GetMapping;
8import org.springframework.web.bind.annotation.RestController;
9
10/**
11 * @description::sentinel 测试类
12 * @author: zzx
13 * @createDate: 2020/9/26
14 * @version: 1.0
15*/
16 @RestController
17public class TestAsyncController {
18
19 @Autowired
20private AsyncService asyncService;
21
22 @GetMapping("/async")
23public void hello(){
24//使⽤限流规则
25 AsyncEntry asyncEntry = null;
26try {
27//被保护的资源
28 asyncEntry = SphU.asyncEntry("Sentinel_AsyncEntry");//限流⼊⼝
29 asyncService.hello();//调⽤异步的⽅法,被保护的资源
30 } catch (BlockException | InterruptedException e) {
31 System.out.println("限流后逻辑处理");
32 } finally {
33if(asyncEntry != null){
34 asyncEntry.exit(); //限流的出⼝
35 }
36 }
37 }
38 }
注解⽅式定义资源 [重点]:Sentinel⽀持通过注解 @SentinelResource 定义资源并配置 blockHandler函数来进⾏限流之后的处理。
【1】在本地应⽤的 pom.xml中引⼊依赖:因为 Sentinel中使⽤ AspectJ的扩展⽤于⾃动定义资源、处理 BlockException等,所以需要在项⽬引⼊ sentinel-annotation-aspectj依赖;
1<dependency>
2<groupId>com.alibaba.csp</groupId>
3<artifactId>sentinel-annotation-aspectj</artifactId>
4<version>1.7.2</version>
5</dependency>
【2】创建 AspectJ 的配置类;
1import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
2import org.springframework.context.annotation.Bean;
3import org.springframework.context.annotation.Configuration;
4
5/**
6 * @description: 配置⽂件,创建引⼊jar中的实例
7 * @author: zzx
8 * @createDate: 2020/9/27
9 * @version: 1.0
10*/
11 @Configuration
12public class SentinelAspectConfiguration {
13
14 @Bean
15public SentinelResourceAspect sentinelResourceAspect(){
16return new SentinelResourceAspect();
17 }
18 }
【3】创建 TestAnnController,实现限流控制;@SentinelResource注解⽤来标识资源是否限流、降级。
例⼦中该注解的属
性‘Sentinel_Ann’表⽰资源名。
@SentinelResource 还提供了其他额外的属性如 blockHandler来指定被限流后的操作。
1import com.alibaba.csp.sentinel.AsyncEntry;
2import com.alibaba.csp.sentinel.SphU;
3import com.alibaba.csp.sentinel.annotation.SentinelResource;
4import com.alibaba.csp.sentinel.slots.block.BlockException;
5import com.zzx.sentinelquickstart.server.AsyncService;
6import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.web.bind.annotation.GetMapping;
8import org.springframework.web.bind.annotation.RestController;
9
10/**
11 * @description::sentinel 测试类
12 * @author: zzx
13 * @createDate: 2020/9/26
14 * @version: 1.0
15*/
16 @RestController
17public class TestAnnController {
18
19 @Autowired
20private AsyncService asyncService;
21
22//设置资源名称和限流降级的处理函数
23 @SentinelResource(value = "Sentinel_Ann", blockHandler = "execeptionHandler")
24 @GetMapping("/ann")
25public String hello(){
26//使⽤限流规则
27return "Hello Sentinel";
28 }
29
30public String execeptionHandler(BlockException e){
31 e.printStackTrace();
32return "系统繁忙,请稍等";
33 }
34 }
三、Sentinel ⾼级
1、Sentinel 和 SpringCloud整合
为了减少开发的复杂程度,我们对⼤部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了适配。
你只需要引⼊对应的依赖即可⽅便地整合 Sentinel。
如果要实现 SpringCloud和 Sentinel的整合,可以通过引⼊ Spring Cloud Alibaba Sentinel来⽅便地整合 Sentinel。
Spring Cloud Alibaba 是阿⾥巴巴提供的,致⼒于提供微服务开发的⼀站式解决⽅案。
Spring Cloud Alibaba 默认为 Sentinel整合Servlet、RestTemplate、FeignClient和 Spring WebFlux。
Sentinel 在 Spring Cloud⽣态中,不仅补全了 Hystrix 在 Servlet和 RestTemplate 这⼀块的空⽩,⽽且还完全兼容了 Hystrix在 FeignClient中限流降级和⽤法,并且⽀持运⾏时灵活地配置和调整限流降级规则。
1<dependency>
2<groupId>com.alibaba.cloud</groupId>
3<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
4<version>2.1.0.RELEASE</version>
5</dependency>
【2】在 application.properties中配置本地项⽬接⼊本地控制台。
1 # 设置应⽤名称
2 =SpringCloudSentinel
3 # 设置 Sentinel连接控制台的主机地址和端⼝
4 spring.cloud.sentinel.transport.dashboard=localhost:9000
2、Sentinel 对 Feign的⽀持
Sentinel 适配了 Feign组件。
如果想使⽤,除了引⼊ spring-cloud-starter-alibaba-sentinel的依赖外,还需要如下配置:
【1】配置⽂件打开 Sentinel对 Feign的⽀持:feign.sentinel.enabled=true;
1 # 设置 Sentinel连接控制台的主机地址和端⼝
2 spring.cloud.sentinel.transport.dashboard=localhost:9000
3 #开启 sentinel 对 Feign的⽀持
4 feign.sentinel.enabled=true
3、Sentinel 对 Spring Cloud Gateway的⽀持
从 1.6.0版本开始,Sentinel 提供了 SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:
【1】route 维度:即在 Spring配置⽂件中配置的路由条⽬,资源名对应的 routeId;
【2】⾃定义 API维度:⽤户可以利⽤ Sentinel 提供的API 来⾃定义⼀些 API分组;
整合 sentinel:⽹关微服务配置好之后,就可以开始整合 Spring Cloud GateWay 和 Sentinel 了。
【1】在 sentinel_gateway的 pom.xml中引⼊依赖:
1<dependency>
2<groupId>com.alibaba.cloud</groupId>
3<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
4<version>2.1.0.RELEASE</version>
5</dependency>
6<dependency>
7<groupId>com.alibaba.cloud</groupId>
8<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
9<version>2.1.0.RELEASE</version>
10</dependency>
【2】创建 GatewayConfiguration配置类,配置流控降级回调操作。
1 @Component
2public class GatewayConfiguration {
3 @PostConstruct
4public void doInit(){
5//限流回调函数
6 GatewayCallbackManager.setBlockHandler(new BlockRequestHandler(){
7//当请求被限流时调⽤的⽅法
8 @Override
9public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
10return ServerResponse.status(200).syncBody("系统繁忙,请稍等");
11 }
12 });
13 }
14 }
四、Sentinel 规则
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后⽴即⽣效。
同时 Sentinel也提供相关 API,供开发者定制⾃⼰的规则策略。
Sentinel 主要⽀持以下⼏种规则:
1、流量控制规则
流量控制(flow control),其原理是监控应⽤流量的 QPS或并发线程数等指标,当达到指定的阈值时对流量进⾏控制,以避免被瞬时的流量⾼峰冲垮,从⽽保障应⽤的⾼可⽤性。
流量控制主要有两种⽅式:
【1】并发线程数:并发线程数限流⽤于保护业务线程数不被耗尽;
【2】QPS:当 QPS超过某个阈值的时候,则采取措施进⾏流量控制;
⼀条限流规则主要由以下⼏个因素组成,我们可以组合元素来实现不同的限流效果:
① resource:资源名,即限流规则的作⽤对象;
② count:限流阈值;
③ grade:限流阈值类型(QPS或并发线程数);
④ limitApp:流控针对的调⽤来源,若为 default 则不区分调⽤来源;
⑤ strategy:调⽤关系限流策略;
⑥ controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
●直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)⽅式是默认的流量控制⽅式,当 QPS超过任意规则的阈值后,新的请求就会被⽴即拒绝,拒绝⽅式为抛出 FlowException。
这种⽅式适⽤于对系统处理能⼒确切已知的情况下,⽐如通过压测确定了系统的准确⽔位时。
● Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)⽅式,即预热/冷启动⽅式。
当系统长期处于低⽔位的情况下,当流量突然增加时,直接把系统拉升到⾼⽔位可能瞬间把系统压垮。
通过 “冷启动”,让通过的流量缓慢增加,在⼀定时间内逐渐增加到阈值上限,给冷系统⼀个预热时间,避免冷系统被压垮。
●排队等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)⽅式会严格控制请求通过的间隔时间,让请求以匀速的速度通过,对应的是漏桶算法。
同⼀个资源可以同时有多个限流规则,检查规则时会依次检查。
2、熔断降级规则
熔断降级会在链路中某个资源出现不稳定状态时(例如调⽤超时或异常⽐例升⾼),对这个资源的调⽤进⾏限制,让请求快速失败,避免影响到其它的资源⽽导致级联错误。
当资源被降级后,在接下来的降级时间窗⼝之内,对该资源的调⽤都⾃动熔断(默认的⾏为是抛出DegradeException)
重要的属性:
Field说明默认值
resource资源名,即限流规则的作⽤对象
count阈值
grade熔断策略,⽀持秒级RT/秒级异常⽐例/分钟级异常数秒级平均RT rtSlowRequestAmount RT模式下1s内连续多个请求的平均 RT超出阈值⽅可触发熔断5
timeWindow降级的时间,单位为 s
minRequestAmount异常熔断的触发最⼩请求数,请求数⼩于该值时即使异常⽐率超出阈值也不会熔断5
同⼀个资源可以同时有多个降级规则。
熔断策略详解:
【1】平均响应时间(DEGRADE_GRADE_RT):当1s内持续进⼊ N个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以ms为单位),那么在接下的时间(DegradeRule中的 timeWindow,以 s为单位)之内,对这个⽅法的调⽤都会⾃动地熔断(抛出
DegradeException)。
【2】异常⽐例(DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量>=N(可配置),并且每秒异常总数占通过量的⽐值超过阈值(DegradeRule 中的 count)之后,资源进⼊降级状态,在接下来的时间(DegradeRule中的timeWindow,以 s为单位)之内,对这个⽅法的调⽤都会⾃动地返回。
异常⽐率的阈值范围0-1。
【3】异常数(DEGRADE_GRADE_EXCEPTION_COUNT):当资源近1分钟的异常数⽬超过阈值之后会进⾏熔断。
注意由于统计时间是分钟级别的,若 timeWindow⼩于 60s,则结束熔断状态后仍可能再进⼊熔断状态。
【通过代码定义熔断规则】:每次熔断时间为设置的TimeWindow的时长。
1package com.zzx.sentinelquickstart.controller;
2
3import com.alibaba.csp.sentinel.annotation.SentinelResource;
4import com.alibaba.csp.sentinel.slots.block.BlockException;
5import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
7import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
8import com.zzx.sentinelquickstart.server.AsyncService;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.web.bind.annotation.GetMapping;
11import org.springframework.web.bind.annotation.RestController;
12import javax.annotation.PostConstruct;
13import java.util.ArrayList;
14import java.util.List;
15
16/**
17 * @description::sentinel 测试类
18 * @author: zzx
19 * @createDate: 2020/9/26
20 * @version: 1.0
21*/
22 @RestController
23public class TestAnnController {
24
25 @Autowired
26private AsyncService asyncService;
27
28//设置资源名称和限流降级的处理函数
29 @SentinelResource(value = "Sentinel_Rule", blockHandler = "execeptionHandler")
30 @GetMapping("/ann")
31public String hello(){
32//使⽤限流规则
33return "Hello Sentinel";
34 }
35
36/**
37 * @Description 定义熔断降级规则
38 * @Author zhengzhaoxiang
39 * @Date 2020/10/1 8:16
40 * @Param []
41 * @Return void
42*/
43 @PostConstruct
44public void initDegradeRule(){
45//1、创建存放规则的集合
46 List<DegradeRule> rules = new ArrayList<>();
47//2、创建熔断降级规则
48 DegradeRule degradeRule = new DegradeRule();
49//定义资源名称
50 degradeRule.setResource("Sentinel_Rule");
51//定义规则类型:平局响应时间类型
52 degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
53//定义阈值
54 degradeRule.setCount(0.01);
55//降级时间
56 degradeRule.setTimeWindow(10);
57//3、讲规则保存到集合中
58 rules.add(degradeRule);
59//4、加载规则
60 DegradeRuleManager.loadRules(rules);
61 }
62
63//被限流或降级的处理函数
64public String execeptionHandler(BlockException e){
65 e.printStackTrace();
66return "系统繁忙,请稍等";
67 }
68 }
3、系统保护规则
Sentinel 系统⾃适应限流从整体维度对应⽤⼊⼝流量进⾏控制,结合应⽤的 Load、CPU使⽤率、总体平均RT、⼊⼝ QPS和并发线程数等⼏个维度的监控指标,通过⾃适应的流控策略,让系统的⼊⼝流量和系统的负载达到⼀个平衡,让系统尽可能保持最⼤吞吐量的同时保证系统整体的稳定性。
系统保护规则是整体维度的,⽽不是资源维度的,并且仅对⼊⼝流量⽣效。
⼊⼝流量指的是进⼊应⽤的流量(EntryType.IN),⽐如 Web服务或 Dubbo服务端接收的请求,都属于⼊⼝流量。
系统规则⽀持以下模式:
【1】CPU使⽤率:当系统 CPU使⽤率超过阈值即触发系统保护,阈值设置范围为0~1,表⽰0%~100%。
【2】Load(仅对 Linux/Unix-like机器⽣效):当系统的 Load1超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。
系统容量由系统的maxQps * minRt计算得出。
【3】并发线程数:当单节点上所有⼊⼝流量的并发线程数达到阈值即触发系统保护。
【4】⼊⼝平均RT:当单节点上所有⼊⼝流量的平均响应时间达到阈值即触发系统保护。
单位是毫秒。
【5】⼊⼝总QPS:当单节点上所有⼊⼝流量的 QPS达到阈值即触发系统保护。
重要的属性:
Field说明默认值
highestSystemLoad load1 触发值,⽤于触发⾃适应控制阶段-1不⽣效
avgRt所有⼊⼝流量的平均响应时间-1不⽣效
maxThread⼊⼝流量的最⼤并发数-1不⽣效
qps所有⼊⼝资源的 QPS-1不⽣效
highestCpuUsage当前系统的 CPU使⽤率-1不⽣效
注意系统规则只针对⼊⼝资源(EntryType=IN)⽣效。
实现⽅案两种如下:【1】本地代码设置
1package com.zzx.sentinelquickstart.controller;
2
3import com.alibaba.csp.sentinel.EntryType;
4import com.alibaba.csp.sentinel.annotation.SentinelResource;
5import com.alibaba.csp.sentinel.slots.system.SystemRule;
6import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
7import org.springframework.web.bind.annotation.GetMapping;
8import org.springframework.web.bind.annotation.RestController;
9import javax.annotation.PostConstruct;
10import java.util.ArrayList;
11import java.util.List;
12
13/**
14 * @description::sentinel 测试类
15 * @author: zzx
16 * @createDate: 2020/9/26
17 * @version: 1.0
18*/
19 @RestController
20public class SysController {
21
22//定义资源设置为⼊⼝资源
23 @SentinelResource(entryType = EntryType.IN)
24 @GetMapping("/ann")
25public String hello(){
26//使⽤限流规则
27return "Hello Sentinel";
28 }
29
30/**
31 * @Description 定义系统⾃适应保护规则
32 * @Author zhengzhaoxiang
33 * @Date 2020/10/1 8:16
34 * @Param []
35 * @Return void
36*/
37 @PostConstruct
38public void initDegradeRule(){
39//1、创建存放规则的集合
40 List<SystemRule> rules = new ArrayList<>();
41//2、创建系统⾃适应保护规则
42 SystemRule degradeRule = new SystemRule();
43//定义资⼊⼝资源的 QPS,参数表⽰允许的最⼤请求数(最⼤)
44 degradeRule.setQps(2);
45//3、讲规则保存到集合中
46 rules.add(degradeRule);
47//4、加载规则
48 SystemRuleManager.loadRules(rules);
49 }
50 }
4、来源访问控制规则(IP⿊⽩名单)
很多时候,我们需要根据调⽤来源判断该次请求是否运⾏放⾏,这时候可以使⽤ Sentinel的来源访问控制(⿊⽩名单控制)的功能。
来源访问控制根据资源的请求来源(origin)判断资源访问是否通过,其余的请求通过。
重要属性:来源访问控制规则(AuthorityRule)⾮常简单,主要有以下配置:
【1】resource:资源名,即限流规则的作⽤对象;
【2】limitApp:请求来源,对应的⿊名单/⽩名单,多个⽤逗号分隔;
【3】strategy:限制模式,AUTHORITY_WHITE为⽩名单模式,AUTHORITY_BLACK为⿊名单模式,默认为⽩名单模式;
实现⽅案两种如下:【1】本地代码设置,设置⿊⽩名单规则
1package com.zzx.sentinelquickstart.controller;
2
3import com.alibaba.csp.sentinel.annotation.SentinelResource;
4import com.alibaba.csp.sentinel.slots.block.BlockException;
5import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
7import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
8import com.zzx.sentinelquickstart.server.AsyncService;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.web.bind.annotation.GetMapping;
11import org.springframework.web.bind.annotation.RestController;
12import javax.annotation.PostConstruct;
13import java.util.ArrayList;
14import java.util.List;
15
16/**
17 * @description::sentinel 测试类
18 * @author: zzx
19 * @createDate: 2020/9/26
20 * @version: 1.0
21*/
22 @RestController
23public class WhiteBlackController {
24
25 @Autowired
26private AsyncService asyncService;
27
28//设置资源名称和限流降级的处理函数
29 @SentinelResource(value = "Sentinel_Rule", blockHandler = "execeptionHandler")
30 @GetMapping("/origin")
31public String hello(){
32//使⽤限流规则
33return "Hello Sentinel";
34 }
35
36/**
37 * @Description 定义⽩名单授权定义规则
38 * @Author zhengzhaoxiang
39 * @Date 2020/10/1 8:16
40 * @Param []
41 * @Return void
42*/
43 @PostConstruct
44public void initWhiteRule(){
45//1、创建存放规则的集合
46 List<AuthorityRule> rules = new ArrayList<>();
47//2、创建授权控制规则
48 AuthorityRule rule = new AuthorityRule();
49//定义资源名称
50 rule.setResource("Sentinel_Rule");
51//定义限制模式⽩名单
52 rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
53//请求来源
54 rule.setLimitApp("192.168.52.1");
55//3、讲规则保存到集合中
56 rules.add(rule);
57//4、加载规则
58 AuthorityRuleManager.loadRules(rules);
59 }
60
61/**
62 * @Description 定义⿊名单授权定义规则
63 * @Author zhengzhaoxiang
64 * @Date 2020/10/1 8:16
65 * @Param []
66 * @Return void
67*/
68 @PostConstruct
69public void initBlackRule(){
70//1、创建存放规则的集合
71 List<AuthorityRule> rules = new ArrayList<>();
72//2、创建授权控制规则
73 AuthorityRule rule = new AuthorityRule();
74//定义资源名称
75 rule.setResource("Sentinel_Rule");
76//定义限制模式⽩名单
77 rule.setStrategy(RuleConstant.AUTHORITY_BLACK);
78//请求来源
79 rule.setLimitApp("127.0.0.1");
80//3、讲规则保存到集合中
81 rules.add(rule);
82//4、加载规则
83 AuthorityRuleManager.loadRules(rules);
84 }
85//被限流或降级的处理函数
86public String execeptionHandler(BlockException e){
87 e.printStackTrace();
88return "系统繁忙,请稍等";
89 }
90 }
设置获取 IP地址的配置类
1package com.zzx.sentinelquickstart.config;
2
3import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
4import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
5import ponent;
6import javax.annotation.PostConstruct;
7import javax.servlet.http.HttpServletRequest;
8
9/**
10 * @description: 获取请求来源的 API
11 * @author: zzx
12 * @createDate: 2020/9/29
13 * @version: 1.0
14*/
15 @Component
16public class SentinelConfiguration {
17 @PostConstruct
18public void doInit(){
19//获取请求来源的 IP地址
20 WebCallbackManager.setRequestOriginParser(new RequestOriginParser() {
21 @Override
22public String parseOrigin(HttpServletRequest httpServletRequest) {
23return httpServletRequest.getRemoteAddr();
24 }
25 });
26 }
27 }
5、动态规则扩展
这⾥演⽰如何使⽤ zk配置规则:【1】Sentinel针对 zk做了相应适配,底层可以采⽤ zk作为规则配置数据源。
使⽤时只需要添加 sentinel-datasource-zookeeper 依赖,如下 pom.xml:
1<dependency>
2<groupId>com.alibaba.cloud</groupId>
3<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
4<version>2.1.0.RELEASE</version>
5</dependency>
6<dependency>
7<groupId>com.alibaba.csp</groupId>
8<artifactId>sentinel-datasource-zookeeper</artifactId>
9<version>1.7.2</version>
10</dependency>
【2】在 application.properties中配置连接 sentinel控制台:
1 # 设置应⽤名称
2 =SentinelZookeeper
3 # 设置 Sentinel连接控制台的主机地址和端⼝
4 spring.cloud.sentinel.transport.dashboard=localhost:9000
【3】创建 zkSentinelConfig,设置客户端修改获取规则的地⽅为从 zk获取规则。
五、Sentinel 主要功能设计理念
在限制的⼿段上,Sentinel 和 Hystrix 采取了完全不⼀样的⽅法。
Hystrix 通过线程池隔离的⽅式,来对依赖(在 Sentinel 的概念中对应资源)进⾏了隔离。
这样做的好处是资源和资源之间做到了最彻底的隔离。
缺点是除了增加了线程切换的成本(过多的线程池导致线程数⽬过多),还需要预先给各个资源做线程池⼤⼩的分配。
如下图:
Sentinel 对这个问题采取了两种⼿段:
【1】通过并发线程数进⾏限制:和资源池隔离的⽅法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。
这样不但没有线程切换的损耗,也不需要您预先分配线程池的⼤⼩。
当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。
当线程数在特定资源上堆积到⼀定的数量之后,对该资源的新请求就会被拒绝。
堆积的线程完成任务后才开始继续接收请求。
【2】通过响应时间对资源进⾏降级:除了对并发线程数进⾏控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。
当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗⼝之后才重新恢复。
系统负载保护:Sentinel 同时提供系统维度的⾃适应保护能⼒。
防⽌雪崩,是系统防护中重要的⼀环。
当系统负载较⾼的时候,如果还持续让请求进⼊,可能会导致系统崩溃,⽆法响应。
在集群环境下,⽹络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。
如果这个时候其它的机器也处在⼀个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可⽤。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的⼊⼝流量和系统的负载达到⼀个平衡,保证系统在能⼒范围之内处理最多的请求。
1、Sentinel 的⼯作机制
Sentinel 的⼯作机制如下:
【1】对主流框架提供适配或者显⽰的 API,来定义需要保护的资源,并提供设施对资源进⾏实时统计和调⽤链路分析。
【2】根据预设的规则,结合对资源的实时统计信息,对流量进⾏控制。
同时,Sentinel提供开放的接⼝,⽅便你定义及改变规则。
【3】Sentinel 提供实时的监控系统,⽅便你快速了解⽬前系统的状态;。