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 的特性
【1】丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
【2】完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
【3】广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
【4】完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
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>
【2】创建 Sentinel 限流规则方案一 [建议使用](在 Sentinel控制台设置流控规则)
创建 Sentinel 限流规则方案二 [不建议使用](在应用中使用代码编写流控规则)
1 package com.zzx.sentinelquickstart.controller;
2
3 import com.alibaba.csp.sentinel.Entry;
4 import com.alibaba.csp.sentinel.SphU;
5 import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6 import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
7 import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
8 import org.springframework.web.bind.annotation.GetMapping;
9 import org.springframework.web.bind.annotation.RestController;
10
11 import javax.annotation.PostConstruct;
12 import java.util.ArrayList;
13 import java.util.List;
14
15 /**
16 * @description::sentinel 测试类
17 * @author: zzx
18 * @createDate: 2020/9/26
19 * @version: 1.0
20 */
21 @RestController
22 public class TestController {
23
24 @GetMapping("/hello")
25 public String hello(){
26 //使用限流规则
27 try(Entry entry = SphU.entry("Hello")) {//限流入口
28 //被保护的规则
29 return "hello Sentinel";
30 }catch (Exception e){
31 e.printStackTrace();
32 return "系统繁忙,请稍等";
33 }
34 }
35
36 /**
37 * @Description 定义限流规则
38 * @Author zhengzhaoxiang
39 * @Date 2020/9/26 8:58
40 * @Param
41 * @Return
42 */
43 @PostConstruct //当前类的构造函数执行之后执行
44 public 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 }
【3】测试:当 1秒内点击两次以内,正常返回,超过2次,则返回 “系统繁忙,请稍等“
搭建本地 Sentinel 控制台:Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、实时监控(单机和集群),规则管理和推送的功能。本地控制台搭建步骤:
【1】下载 Sentinel 控制台 jar包:链接
【2】启动 Sentinel 控制台:jdk1.8及以上,使用如下命令启动控制台:9000是端口;
java -Dserver.port=9000 -jar sentinel-dashboard-1.7.2.jar
【3】访问 Sentinel 控制台:通过浏览器打开 http:localhost:9000/ 即可访问 Sentinel控制台,默认用户名和密码都是 sentinel;
本地应用接入本地 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控制台的主机地址和端口。 project.name设置本地在 Sentinel 控制台中的名称
2 -Dcsp.sentinel.dashboard.server=localhost:9000 -Dproject.name=SentinelQuickStart
【3】运行测试: 重启本地应用并重新通过浏览器访问本地请求,快速刷新几次,查看控制台中的实时监控情况。
1、Sentinel 定义资源的方式
抛出异常的方式定义资源 [了解]:Sentinel中的 SphU包含了 try-catch风格的 API。用这种方式,当资源发生了限流会抛出 BlockException。这个时候可以捕获异常,进行限流之后的逻辑处理。关键代码如下:
1 //使用限流规则
2 try(Entry entry = SphU.entry("Hello")) {//限流入口
3 //被保护的规则
4 return "hello Sentinel";
5 }catch (Exception e){
6 e.printStackTrace();
7 return "系统繁忙,请稍等";
8 }
返回布尔值方式定义资源 [了解]:Sentinel中的 SphO 提供 if-else风格的API。用这种方式,当资源发生了限流之后就返回 false,这个时候可以根据返回值,进行限流之后的逻辑处理。
【1】在 Sentinel_quick_start 项目中创建 TestBooleanController使用返回布尔值的方式定义资源。需要注意的是 SphO.entry(x)需要与 SphO.exit()方法成对出现,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。
1 package com.zzx.sentinelquickstart.controller;
2
3 import com.alibaba.csp.sentinel.SphO;
4 import org.springframework.web.bind.annotation.GetMapping;
5 import 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
14 public class TestBooleanController {
15
16 @GetMapping("/boolean")
17 public Boolean hello(){
18 //使用限流规则
19 if(SphO.entry("Sentinel_Boolean")) {//限流入口
20 try {
21 //被保护的资源
22 System.out.println("被保护的资源");
23 return true;
24 } finally {
25 SphO.exit();
26 }
27 }else{
28 //被限流或降级的处理
29 System.out.println("被限流或降级的处理");
30 return false;
31 }
32 }
33 }
【2】测试:添加限流规则,随后访问请求,当超过 QPS=2的时候,就会返回 flase,正常返回 true。
异步调用支持 [了解]:Sentinel 支持异步调用链路的统计。在异步调用中,需要通过 SphU.asyncEntry(x)方法定义资源,并通常需要在异步的回调函数中调用 exit方法。
【1】在本地应用的引导类中添加 @EnableAsync,表示 springboot项目开始异步调用支持;
1 @SpringBootApplication
2 @EnableAsync//开启异步调用的支持
3 public class SentinelQuickStartApplication {
4 public static void main(String[] args) {
5 SpringApplication.run(SentinelQuickStartApplication.class, args);
6 }
7 }
【2】创建 AsyncService 编写异步调用方法;
1 import org.springframework.scheduling.annotation.Async;
2 import org.springframework.stereotype.Service;
3
4 /**
5 * @description: 异步方法服务类
6 * @author: zzx
7 * @createDate: 2020/9/27
8 * @version: 1.0
9 */
10 @Service
11 public class AsyncService {
12
13 @Async //表示方法是异步调用方法
14 public void hello() throws InterruptedException {
15 System.out.println("异步的开始");
16 Thread.sleep(5000);
17 System.out.println("异步的结束");
18 }
19 }
【3】创建 TestAsyncController,实现异步调用限流控制;
1 import com.alibaba.csp.sentinel.AsyncEntry;
2 import com.alibaba.csp.sentinel.SphO;
3 import com.alibaba.csp.sentinel.SphU;
4 import com.alibaba.csp.sentinel.slots.block.BlockException;
5 import com.zzx.sentinelquickstart.server.AsyncService;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.web.bind.annotation.GetMapping;
8 import 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
17 public class TestAsyncController {
18
19 @Autowired
20 private AsyncService asyncService;
21
22 @GetMapping("/async")
23 public void hello(){
24 //使用限流规则
25 AsyncEntry asyncEntry = null;
26 try {
27 //被保护的资源
28 asyncEntry = SphU.asyncEntry("Sentinel_AsyncEntry");//限流入口
29 asyncService.hello();//调用异步的方法,被保护的资源
30 } catch (BlockException | InterruptedException e) {
31 System.out.println("限流后逻辑处理");
32 } finally {
33 if(asyncEntry != null){
34 asyncEntry.exit(); //限流的出口
35 }
36 }
37 }
38 }
【4】测试:当设置限流规则后,QPS>2时就会出现异常中捕获的信息,当QPS<=2时,则执行异常方法hello中的内容;
注解方式定义资源 [重点]: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 的配置类;
1 import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
2 import org.springframework.context.annotation.Bean;
3 import 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
12 public class SentinelAspectConfiguration {
13
14 @Bean
15 public SentinelResourceAspect sentinelResourceAspect(){
16 return new SentinelResourceAspect();
17 }
18 }
【3】创建 TestAnnController,实现限流控制;@SentinelResource注解用来标识资源是否限流、降级。例子中该注解的属性‘Sentinel_Ann’表示资源名。@SentinelResource 还提供了其他额外的属性如 blockHandler来指定被限流后的操作。
1 import com.alibaba.csp.sentinel.AsyncEntry;
2 import com.alibaba.csp.sentinel.SphU;
3 import com.alibaba.csp.sentinel.annotation.SentinelResource;
4 import com.alibaba.csp.sentinel.slots.block.BlockException;
5 import com.zzx.sentinelquickstart.server.AsyncService;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.web.bind.annotation.GetMapping;
8 import 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
17 public class TestAnnController {
18
19 @Autowired
20 private AsyncService asyncService;
21
22 //设置资源名称 和 限流降级的处理函数
23 @SentinelResource(value = "Sentinel_Ann", blockHandler = "execeptionHandler")
24 @GetMapping("/ann")
25 public String hello(){
26 //使用限流规则
27 return "Hello Sentinel";
28 }
29
30 public String execeptionHandler(BlockException e){
31 e.printStackTrace();
32 return "系统繁忙,请稍等";
33 }
34 }
【4】运行测试:在 Sentinel控制台中设置关于 “Sentinel_Ann”资源的流控规则后。当访问请求的 QPS超过2时就会调用 blockHandler 定义的方法。
三、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中限流降级和用法,并且支持运行时灵活地配置和调整限流降级规则。
需求:使用 SpringCloud+Sentinel实现访问 http://localhost:8080/ann 路径的流量控制,引用上面的案例。
具体步骤:【1】创建 springboot 项目,在项目中引入 spring-cloud-start-alibaba-sentinel依赖
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 spring.application.name=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
【2】在 Sentinel控制台中增加关于资源的流控规则,Sentinel和 Feign整合时,流控规则编写形式为:http请求方式:协议://服务名/请求路径跟参数,例如:GET:http://sentinel-feign-provider/hello。
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
2 public class GatewayConfiguration {
3 @PostConstruct
4 public void doInit(){
5 //限流回调函数
6 GatewayCallbackManager.setBlockHandler(new BlockRequestHandler(){
7 //当请求被限流时调用的方法
8 @Override
9 public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
10 return ServerResponse.status(200).syncBody("系统繁忙,请稍等");
11 }
12 });
13 }
14 }
【3】在 application.yml中配置 Sentinel控制台的访问地址,同上;
【4】运行测试:启动项目,在 Sentinel控制台中增加关于资源的流控规则,Sentinel在适配 Spring Cloud Gateway时提供了两种配置资料的规则:
route 维度规则定义:在 sentinel控制台中增加流控规则,API类型选择 “Route ID”,API名称为网关配置的路由Id,QPS阈值设置为2自定义 API维度:先配置 API管理,匹配串设置为路由规则中匹配的 “断言”信息。
然后点击流控规则,新增网关流控规则。选择 API分组:
四、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的时长。
1 package com.zzx.sentinelquickstart.controller;
2
3 import com.alibaba.csp.sentinel.annotation.SentinelResource;
4 import com.alibaba.csp.sentinel.slots.block.BlockException;
5 import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6 import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
7 import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
8 import com.zzx.sentinelquickstart.server.AsyncService;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.web.bind.annotation.GetMapping;
11 import org.springframework.web.bind.annotation.RestController;
12 import javax.annotation.PostConstruct;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17 * @description::sentinel 测试类
18 * @author: zzx
19 * @createDate: 2020/9/26
20 * @version: 1.0
21 */
22 @RestController
23 public class TestAnnController {
24
25 @Autowired
26 private AsyncService asyncService;
27
28 //设置资源名称 和 限流降级的处理函数
29 @SentinelResource(value = "Sentinel_Rule", blockHandler = "execeptionHandler")
30 @GetMapping("/ann")
31 public String hello(){
32 //使用限流规则
33 return "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
44 public 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 //被限流或降级的处理函数
64 public String execeptionHandler(BlockException e){
65 e.printStackTrace();
66 return "系统繁忙,请稍等";
67 }
68 }
【在 Sentinel控制台动态设置】:
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】 本地代码设置
1 package com.zzx.sentinelquickstart.controller;
2
3 import com.alibaba.csp.sentinel.EntryType;
4 import com.alibaba.csp.sentinel.annotation.SentinelResource;
5 import com.alibaba.csp.sentinel.slots.system.SystemRule;
6 import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
7 import org.springframework.web.bind.annotation.GetMapping;
8 import org.springframework.web.bind.annotation.RestController;
9 import javax.annotation.PostConstruct;
10 import java.util.ArrayList;
11 import java.util.List;
12
13 /**
14 * @description::sentinel 测试类
15 * @author: zzx
16 * @createDate: 2020/9/26
17 * @version: 1.0
18 */
19 @RestController
20 public class SysController {
21
22 //定义资源 设置为入口资源
23 @SentinelResource(entryType = EntryType.IN)
24 @GetMapping("/ann")
25 public String hello(){
26 //使用限流规则
27 return "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
38 public 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 }
【2】Sentinel 控制台动态设置
4、来源访问控制规则(IP黑白名单)
很多时候,我们需要根据调用来源判断该次请求是否运行放行,这时候可以使用 Sentinel的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)判断资源访问是否通过,其余的请求通过。
重要属性:来源访问控制规则(AuthorityRule)非常简单,主要有以下配置:
【1】resource:资源名,即限流规则的作用对象;
【2】limitApp:请求来源,对应的黑名单/白名单,多个用逗号分隔;
【3】strategy:限制模式,AUTHORITY_WHITE为白名单模式,AUTHORITY_BLACK为黑名单模式,默认为白名单模式;
实现方案两种如下:【1】本地代码设置,设置黑白名单规则
1 package com.zzx.sentinelquickstart.controller;
2
3 import com.alibaba.csp.sentinel.annotation.SentinelResource;
4 import com.alibaba.csp.sentinel.slots.block.BlockException;
5 import com.alibaba.csp.sentinel.slots.block.RuleConstant;
6 import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
7 import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
8 import com.zzx.sentinelquickstart.server.AsyncService;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.web.bind.annotation.GetMapping;
11 import org.springframework.web.bind.annotation.RestController;
12 import javax.annotation.PostConstruct;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17 * @description::sentinel 测试类
18 * @author: zzx
19 * @createDate: 2020/9/26
20 * @version: 1.0
21 */
22 @RestController
23 public class WhiteBlackController {
24
25 @Autowired
26 private AsyncService asyncService;
27
28 //设置资源名称 和 限流降级的处理函数
29 @SentinelResource(value = "Sentinel_Rule", blockHandler = "execeptionHandler")
30 @GetMapping("/origin")
31 public String hello(){
32 //使用限流规则
33 return "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
44 public 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
69 public 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 //被限流或降级的处理函数
86 public String execeptionHandler(BlockException e){
87 e.printStackTrace();
88 return "系统繁忙,请稍等";
89 }
90 }
设置获取 IP地址的配置类
1 package com.zzx.sentinelquickstart.config;
2
3 import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
4 import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
5 import org.springframework.stereotype.Component;
6 import javax.annotation.PostConstruct;
7 import javax.servlet.http.HttpServletRequest;
8
9 /**
10 * @description: 获取请求来源的 API
11 * @author: zzx
12 * @createDate: 2020/9/29
13 * @version: 1.0
14 */
15 @Component
16 public class SentinelConfiguration {
17 @PostConstruct
18 public void doInit(){
19 //获取请求来源的 IP地址
20 WebCallbackManager.setRequestOriginParser(new RequestOriginParser() {
21 @Override
22 public String parseOrigin(HttpServletRequest httpServletRequest) {
23 return httpServletRequest.getRemoteAddr();
24 }
25 });
26 }
27 }
【2】Sentinel控制台动态设置
5、动态规则扩展
前面不管是通过 Java代码还是通过 Sentinel控制台的方式去设置限流规则,都属于手动方式,不够灵活。这种方式一般仅用于测试和演示,生产环境一般通过动态规则的方式来动态管理限流规则。也就是说,很多时候限流规则会被存储在文件、数据库或者配置中心中。Sentinel的 DataSorce 接口给我们提供了对接任意配置源的能力。官方推荐通过控制台设置规则后将规则推送到统一的规则管理中心,客户端实现 ReadableDataSource接口端监听规则中心实时获取变更,流程如下:常见的实现方式有:
【1】拉取式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则管理中心可以是文件,甚至是 VCS等。这样做的方式是简单,缺点是无法及时获取变更;实现拉模式的数据源最简单的方式是继承 AutoRefreshDataSource抽象类,然后实现 readSource() 方法,在该方法里从指定数据源读取字符串格式的配置数据。
【2】推送式:规则管理中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 zk、Apollo等作为规则管理中心。这种方式有更好的实时性和一致性保证。实现推模式的数据源最简单的方式是继承 AbstractDataSource 抽象类,在其结构方法中添加监听器,并实现 readSource() 从指定数据源读取字符串格式的配置数据。
这里演示如何使用 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 spring.application.name=SentinelZookeeper
3 # 设置 Sentinel连接控制台的主机地址和端口
4 spring.cloud.sentinel.transport.dashboard=localhost:9000
【3】创建 zkSentinelConfig,设置客户端修改获取规则的地方为从 zk获取规则。
五、Sentinel 主要功能设计理念
流量控制:流量控制在网络传输中是一个常用概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:流量控制设计理念:流量控制有以下几个角度:
【1】资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
【2】运行指标,例如 QPS、线程池、系统负载等;
【3】控制的效果,例如直接限流、冷启动、排队等;
Sentinel 的设计理念是让你自由选择控制的角度,并进行灵活组合,从而达到想要的效果;
熔断降级:除了流量控制以外,及时对调用链路中的不稳定因素进行熔断也是 Sentinel的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求发生堆积,进而导致级联错误。Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。Hystrix 通过线程池隔离的方式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多),还需要预先给各个资源做线程池大小的分配。 如下图:
Sentinel 对这个问题采取了两种手段:
【1】通过并发线程数进行限制:和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
【2】通过响应时间对资源进行降级:除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
系统负载保护:Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
1、Sentinel 的工作机制
Sentinel 的工作机制如下:
【1】对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
【2】根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel提供开放的接口,方便你定义及改变规则。
【3】Sentinel 提供实时的监控系统,方便你快速了解目前系统的状态;
Sentinel 流量控制的更多相关文章
- sentinel流量控制和熔断降级执行流程之源码分析
前言: sentinel是阿里针对服务流量控制.熔断降级的框架,如何使用官方都有很详细的文档,下载它的源码包 里面对各大主流框都做了适配按理,本系列文章目的 主要通过源码分析sentinel流量控制和 ...
- 【Day02】Spring Cloud组件的使用--Nacos配置中心、sentinel流量控制、服务网关Gateway、RocketMQ、服务调用链路(Sleuth、zipkin)
今日内容 一.配置中心 1.遗留问题 yml配置,每一次都需要重启项目 需要不重启项目拿到更新的结果 引出:配置中心 选择:Spring Cloud Config组件 / Alibaba的Nacos( ...
- Sentinel :微服务哨兵
1. Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性. Sentin ...
- Sentinel熔断降级
sentinel流量控制 Sentinel流量控制&服务熔断降级介绍 流量控制介绍 在这里我用景区的例子解释一下 一个旅游景点日接待游客数量为8K,8K以后的游客就无法买票进去景区. 对应编程 ...
- Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(JMeter模拟测试)
目录 一. Sentinel概念 1. 什么是Sentinel? 2. Sentinel功能特性 3. Sentinel VS Hystrix 二. Docker部署Sentinel Dashboar ...
- Spring Cloud Alibaba(12)---Gatway概述、简单示例
Gatway概述.项目搭建 前言 有关网关的概念之前这里不在概述,因为之前在写zuul网关的时候有详细陈述过,地址如下: SpringCloud(7)---网关概念.Zuul项目搭建 SpringCl ...
- 认识 Spring Cloud Alibaba
个人理解 Spring Cloud Alibaba 就是 Spring Cloud 的微服务规范的一种实现,外加一些阿里云的商业组件 Spring Cloud 是什么 Spring Cloud 为开发 ...
- 详细剖析Spring Cloud 和Spring Cloud Alibaba的前世今生
我们知道spring cloud可以用来开发微服务,但是应该很少有人真正知道Spring Cloud是什么. 官方的解释是:spring cloud提供了一些可以让开发者快速构建分布式应用的工具,这些 ...
- Spring Cloud Alibaba微服务一站式解决方案-开篇v2.2.1.RELEASE
学习路线 **本人博客网站 **IT小神 www.itxiaoshen.com 生态概述 架构演进 什么是微服务 https://martinfowler.com/microservices/ Mic ...
- 主流微服务一站式解决方案Spring Cloud Alibaba入门看这篇就足够了
学习路线 **本人博客网站 **IT小神 www.itxiaoshen.com 生态概述 架构演进 什么是微服务 https://martinfowler.com/microservices/ Mic ...
随机推荐
- POJ--2386题C++实现
本题利用深度遍历的穷竭搜索法进行解题,即对每一个元素都对其进行各个方向的深度遍历,穷尽其周围 #include<iostream>#include<cstdio>using n ...
- Java中finalize()方法的使用
参考:https://blog.csdn.net/m0_64624615/article/details/126326921 垃圾回收器
- elelment中el-cascader怎样自定义显示的lable 与value
1.后端返回的数据类型 2.页面代码 3.重点在于 :props="{ value: 'id',label: 'className',children: 'childNode'}" ...
- visio2019 破解
链接:https://pan.baidu.com/s/14AU8GFXhgjp87pK1bIK8UA?pwd=ju61 提取码:ju61 --来自百度网盘超级会员V5的分享 可能需要关闭防火墙和win ...
- GIMP选择,GIMP画布大小,GIMP图层
基本概念 1. 画布 2. 图层 你只能操作一个图层--就是你选中的.就看起来所有的图像都在一起,但是不同的图层中的图像是不同,不能操作没有选中的图层. 对于选择操作,要注意你选中的图层. 要获取图像 ...
- MD5加密汇总
1 #region MD5 2 /// <summary> 3 /// 16位MD5加密 4 /// </summary> 5 /// <param name=" ...
- 第12组 Beta冲刺 (2/5)
1.1基本情况 ·队名:美少女战士 ·组长博客:https://www.cnblogs.com/yaningscnblogs/p/14016602.html ·作业博客:https://edu.cnb ...
- jsp第10个作业
package Servlet; import JDBC.JDBC; import javax.servlet.ServletException; import javax.servlet.annot ...
- java15配置环境后java_version无反应(不显示“不是内部或外部命令”)
重新装了jdk15来使用eclipse 配置完环境变量之后打开cmd输入 java -version 好家伙,居然一点反映都没有, 然后傻乎乎的跑回去重新配置JAVA_HOME和path 还是没用,细 ...
- HTML Cookie
目录 Cookie是什么 Cookie的属性 Cookie的作用域 Domain 属性 Path 属性 SameSite 属性 Cookie密码验证小案例 效果展示 代码 Cookie是什么 HTTP ...