6 Sentinel流量防卫兵
6.1 Sentinel简介
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
Sentinel是分布式系统的防御系统。
官网: https://sentinelguard.io/zh-cn
github上的官网:https://github.com/alibaba/Sentinel
6.2 Sentinel控制台
无论是服务熔断、服务流控、服务鉴权等,都首先会涉及到相关规则的可视化管理,即通过Sentinel控制台来管理相关规则。所以这里首先来学习Sentinel控制台。
6.2.1 简介
Sentinel控制台是Sentinel的一个轻量级开源GUI控制台,可以提供对Sentinel主机(Sentinel应用)的发现及健康管理、动态配置服务流控、熔断、路由规则的配置与管理。
6.2.2 下载
直接从官方下载打包好的Sentinel Dashboard启动运行。下载链接在Sentinel Dashboard官网。不过,在下载时要先查清楚当前的Spring Cloud Alibaba版本兼容的是哪个Sentinel版本,然后再下载相应Sentinel版本的控制台。
6.2.3 启动
启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。在Sentinel控制jar包所在目录中打开cmd窗口,执行启动命令。
| java -Dserver.port=8888 ^
-Dsentinel.dashboard.auth.username=sentinel ^
-Dsentinel.dashboard.auth.password=111 ^
-jar sentinel-dashboard-1.8.6.jar |
---|
6.2.4 访问
由于还没有其它应用,所以这里仅可以看到当前dashboard应用本身。
6.3 服务降级
由于马上要学习的服务熔断会涉及到服务降级,所以这里先学习服务降级。
6.3.1 概述
服务降级是一种增强用户体验的方式。当用户的请求由于各种原因被拒后,系统返回一个事先设定好的、用户可以接受的,但又令用户并不满意的结果。这种请求处理方式称为服务降级。
6.3.2 Sentinel式方法级降级
6.3.2.1 定义工程
复制02-consumer-nacos-8080工程,重命名为06-consumer-degrade-sentinel-method-8080。
6.3.2.2 添加依赖
除了spring cloud alibaba依赖、Nacos依赖外,还需要再导入Sentinel依赖。由于其它依赖在工程中已经有了,所以这里仅添加Sentinel依赖。
| <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency> |
---|
6.3.2.3 修改处理器类
这里要为控制器类DepartController的getHandle()方法添加服务降级,所以在该方法上添加@SentinelResource注解,并在DepartController类中定义降级方法。
该方法返回值与参数类型必须与原方法的相同,方法名可以随意。不过,也可以在降级方法中增加一个Throwable类型的参数,用于获取到降级时相应异常对象。
6.3.2.4 运行访问
不用启动Provider,直接运行Consumer,就可以看到降级的结果。
6.3.3 Sentinel式类级降级
前面例子中所有控制器方法都需要添加降级方法,若都使用前面的方式,将会导致控制器类非常复杂,不便于后期维护。所以可以将这些降级方法全部定义到一个类中。
6.3.3.1 定义工程
复制02-consumer-nacos-8080工程,重命名为06-consumer-degrade-sentinel-class-8080。
6.3.3.2 添加依赖
除了spring cloud alibaba依赖、Nacos依赖外,还需要再导入Sentinel依赖。由于其它依赖在工程中已经有了,所以这里仅添加Sentinel依赖。
| <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency> |
---|
6.3.3.3 定义降级类
定义的降级类所在包没有要求,类名没有要求。在该类中定义的方法均为业务需要的降级方法。降级类中的方法必须是静态方法,方法返回值与参数类型必须与原方法的相同,方法名可以随意。不过,也可以在降级方法中增加一个Throwable类型的参数,用于获取到降级时相应异常对象。
6.3.3.4 修改处理器类
为处理器DepartController中的getHandle()与list()方法添加@SentinelResource注解,指定具体的降级类的降级方法。
6.3.3.5 运行访问
不用启动Provider,直接运行Consumer,就可以看到降级的结果。
6.3.4 Feign式类级降级
6.3.4.1 定义工程
复制04-consumer-feign-8080工程,并重命名为06-consumer-degrade-feign-8080。这个消费者是通过Feign接口进行消费的。
6.3.4.2 添加依赖
除了spring cloud alibaba依赖、openFeign依赖、Nacos依赖外,还需要再导入Sentinel依赖。由于其它依赖在工程中已经有了,所以这里仅添加Sentinel依赖。
| <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency> |
---|
6.3.4.3 修改配置文件
配置文件中除了要添加sentinel dashboard的配置外,还要开启Feign对Sentinel的支持,默认为false。
另外,spring-cloud-starter-alibaba-sentinel依赖与spring-cloud-starter-openfeign依赖在Spring Boot3.0环境下有冲突,此时需要开启openfeign的一个懒加载功能即可,即设置属性spring.cloud.openfeign.lazy-attributes-resolution的值为true。
6.3.4.4 定义降级类
降级类定义的包与类名没有要求。但要求必须实现Feign接口,且其生命周期要交由Spring容器管理,类上的@RequestMapping的内容要与Controller处理器上的相同,但在最前必须要添加/fallback的URI。
不过,这些要求与学习Hystrix时的要求相同,因为这些要求是Feign的要求,并不是Hystrix或Sentinel本身的要求。
6.3.4.5 修改Feign接口
指定要使得的服务降级类。
6.3.4.6 运行访问
不用启动Provider,直接运行Consumer,就可以看到降级的结果。
6.4 熔断规则
熔断规则用于完成服务熔断。
6.4.1 熔断概念
6.4.1.1 服务雪崩
下面的图都来自于Hystrix官网的wiki中。
https://github.com/netflix/hystrix
上图是用户请求的多个服务(A,H,I,P)均能正常访问并返回的情况。
上图为请求服务I出现问题时,一个用户请求被阻塞的情况。
上图为大量用户请求服务I出现异常,每个阻塞的请求都会占用一个线程。当并发访问量非常大时,这些请求会迅速用完所有线程,从而导致对于其它正常服务的访问请求无法获取系统资源而被拒绝,发生系统崩溃,即发生服务雪崩。
6.4.1.2 服务熔断
为了防止服务雪崩的发生,在发现了对某些资源请求的响应缓慢或调用异常较多时,直接将对这些资源的请求掐断一段时间。而在这段时间内的请求将不再等待超时,而是直接返回事先设定好的降级结果。这些请求将不占用系统资源,从而避免了服务雪崩的发生。这就是服务熔断。
6.4.2 动态熔断配置–默认资源名称
对于服务熔断规则,可以通过Sentinel Dashboard进行动态配置。
6.4.2.1 创建工程
复制06-consumer-degrade-sentinel-method-8080工程并重命名为06-consumer-circuitbreaking-8080。
6.4.2.2 修改配置文件
在配置文件中添加Sentinel控制台的相关配置。
6.4.2.3 修改处理器
将消费者工程中的处理器中所有的@SentinelResource注解注释掉。
6.4.2.4 访问
启动02-provider-nacos-8081提供者工程与该06-consumer-circuitbreaking-8080工程。然后快速访问根据id访问与list访问。
6.4.2.5 dashboard设置规则
在控制台的“实时监控”处就可以看到对这两个接口进行访问的流量实时数据。
同时在“簇点链路”处可以看到这两个访问接口名(即URI)成为默认的“资源名”。即默认情况下,对该微服务的访问请求URI将作为由Sentinel管理的URI名称出现。点击/consumer/depart/get/{id}中的“熔断”,新增熔断规则。
点击“新增”后,会立即跳转到“熔断规则”页面,并显示出刚新增的规则。
以同样的方式再为/consumer/depart/list新增熔断规则。
6.4.2.6 访问2
仅提交一次请求正常访问是没有问题的。
但按F5,快速刷新页面,可以看到其出现了降级。注意要达到每秒3次以上的访问才可看到效果。
而且一旦这个降级结果出现,再刷新一次页面也是看不到正常结果的。因为发生了熔断,熔断时长设置的为30秒。30秒后,再刷新一次页面,仍可看到正常结果。
6.4.2.7 再修改处理器
将前面注释掉的@SentinelResource的注释去掉。
6.4.2.8 dashboard设置规则
再次访问…/get/3请求后,查看控制台的簇点链路。发现新增了一个新的“资源名”:getHandle()方法的全限定方法签名。即只要在处理器方法上添加了@SentinelDashboar注解,那么该处理器方法就具有了默认的Sentinel资源名称:该方法的全限定性方法签名。
当然,点击其对应的“熔断”按钮同样也可以为其设置熔断规则。
6.4.2.9 访问3
仅提交一次请求正常访问是没有问题的。但按F5,快速刷新页面,可以看到其出现了降级。但这次的降级结果则是降级方法执行的结果。
6.4.3 动态熔断配置–指定资源名称
除了默认的名称个,还可以为处理器方法指定名称。
直接在06-consumer-circuitbreaking-8080工程中进行修改。
6.4.3.1 修改控制器类
修改DepartController中的getHandle()方法上的@SentinelResource注解,通过value属性指定当前getHandler()方法作为Sentinel资源时的名称。注意,此时并没有指定降级方法。
6.4.3.2 dashboard设置规则
在启动了消费者工程后,再设置Sentinel控制台。
6.4.3.3 访问
仅提交一次请求正常访问是没有问题的。但按F5快速刷新页面可以看到发生熔断。只不过,返回的页面是500,不是原来给出的“Blocked By Sentinel”。
6.4.3.4 再修改控制器类
为@SentinelResource指定其要使用的的降级方法。
6.4.3.5 访问2
按F5快速刷新页面可以看到发生降级,且降级结果为降级方法执行结果。
6.4.4 API熔断设置
通过API设置熔断规则,即直接将熔断规则定义在代码中的,在应用启动时完成熔断规则的创建与初始化。
为了保证项目运行的安全性,一般会在代码中通过API方式设置默认的熔断规则,以应对平时对系统平台的保护要求。不过,API熔断规则在Dashboard中也是可以查看到并且进行编辑的,编辑后以动态编辑的规则为准。
6.4.4.1 修改启动类
直接在06-consumer-circuitbreaking-8080工程中进行修改。在启动类中添加熔断规则定义。
6.4.4.2 访问
启动06-consumer-circuitbreaking-8080工程,在浏览器中按F5快速访问,发现同样也是可以实现熔断的。
6.4.4.3 修改控制台熔断规则
刷新Sentinel控制台页面,发现熔断规则又出现了。这次出现是因为代码中的API熔断规则被加载到了控制台。点击该规则的“编辑”按钮,对熔断规则进行修改,使其不可能在通过刷新页面这种速度情况下达到熔断。以说明控制台的动态配置优先级要高于API设置的。
保存后再F5刷新页面,发现已经不会出现熔断了。说明控制台的熔断规则动态配置优先级的确高于API设置的。
6.5 自定义异常处理器
当采用URI作为默认Sentinel资源名称,且发生打破规则阈值的异常情况时,Sentinel会抛出一个BlockExcetion异常,而该异常会被BlockedExceptionHandler异常处理器处理。
6.5.1 返回响应流
6.5.1.1 定义处理器
6.5.1.2 访问结果
当发生相应规则异常时,会由自定义的异常处理器来处理。例如,对于熔断异常的处理结果显示为:
6.5.2 跳转到html页面
若感觉返回响应流的内容过于简单,也可将其跳转到相应的指定页面。
6.5.2.1 定义页面
在工程的resources目录下新建META-INF/resources目录,在其中新建一个degrade.html文件。
degrade.html文件内容如下:
再如法炮制定义出flow.html、system.html、param.html与authority.html。
6.5.2.2 定义处理器
6.5.2.3 访问结果
当发生相应规则异常时,会由自定义的异常处理器来处理。例如,对于熔断异常的处理结果显示为:
6.5.3 重定向到URL
当系统采用前后端分离模式时使用页面跳转是不行的,此时可以使用重定向来完成。
6.5.3.1 定义处理器
6.5.3.2 访问结果
当发生相应规则异常时,会由自定义的异常处理器来处理。例如,对于熔断异常的处理结果是,直接跳转到了淘宝官网。
6.6 流控规则
6.6.1 简介
流控规则是用于完成服务流控的。服务流控即对访问流量的控制,也称为服务限流。Sentinel实现流控的原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对再到来的请求进行进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
6.6.2 动态流控
流控规则直接通过Sentinel Dashboard定义,该规则可以随时修改而不需要重启应用。所以这种流控是一种动态流控。
6.6.2.1 定义工程
复制06-consumer-circuitbreaking-8080工程,重命名为06-consumer-flowcontrol-8080。
6.6.2.2 dashboard设置流控规则
在启动了消费者工程后,再设置Sentinel控制台。