1.导学
1.1.软件环境
-
系统:windows10
-
开发工具:IntelliJ IDEA、maven
-
JDK:1.8
1.2.技术储备要求
- spring、springmvc、springboot、springcloud、阿里云、zookeeper
1.3.适合人群
- 初学者
- Sentinel简介
- Sentinel入门
- 开发者
- Sentinel简介
- Sentinel入门
- Sentinel高级
- 测试、运维
- Sentinel简介
- Sentinel入门
- 技术爱好者、性能优化人员、架构师
- Sentinel原理
1.4.课程内容
-
- 流量控制&熔断降级介绍
- Sentinel介绍
-
- Sentinel初体验
- Sentinel流控降级入门
- Sentinel定义资源的方式
-
- Sentinel和SpringCloud整合
- Sentinel对Feign的支持
- Sentinel对Spring Cloud Gateway的支持
- Sentinel实现流量控制
- Sentinel实现熔断降级
- Sentinel实现系统自适应保护
- Sentinel实现授权控制
- Sentinel实现动态规则扩展
-
- Sentinel主要功能设计理念
- Sentinel的工作机制
2.Sentinel简介
2.1.流量控制&熔断降级介绍
2.1.1.流量控制简介
以旅游景点为例,每个旅游景点通常都有最大的接待,不可能无限期地让游客进入,如紫禁城每天只卖8万张票,超过8万游客,不能买票,因为如果超过8万人,景点工作人员可能忙,太拥挤的景点也会影响游客的体验和情绪,也会有安全风险;只卖N张票,这是一种流量限制。
流量控制是网络传输中常用的一个概念,用于调整网络包的发送数据。在网络传输中,任何时要求往往是随机和不可控的,系统的处理能力有限。我们需要根据系统的处理能力来控制流量。
2.1.2.熔断降级简介
在调用系统时,如果调用链路中的资源不稳定,请求最终会积累,如下图所示:
熔断降级可以解决这个问题。所谓熔断降级,就是当检测到调用链路中某一资源的不稳定性能时,如需求响应时间长或异常比例增加时,限制资源调用,使请求快速失败,避免影响其他资源,导致级联故障。
2.1.3.流量控制&熔断降级实现方案
**主页地址:**https://github.com/Netflix/Hystrix/
Hystrix源自Netflix API该团队于2011年开始了弹性工程工作。2012年,Hystrix不断发展成熟,Netflix很多团队都用过。现在,每天都在Netflix上通过Hystrix执行数千亿线程隔离和数千信号隔离调用。这大大提高了正常运行时间和弹性。
主页地址:https://github.com/resilience4j/resilience4j
Resilience4j是受Netflix Hystrix轻量级容错库的启发,但专为Java 设计8和函数编程。很轻,因为这个库只使用Vavr,而Vavr没有其他外部库依赖项。相比之下,Netflix Hystrix对Archaius有编译依赖性,而且Archaius对外部库的依赖性更大。
主页地址:https://github.com/alibaba/Sentinel
Sentinel 它是阿里巴巴为分布式服务架构生产的轻量级流量控制组件,主要以流量为切入点,从流量限制、流量塑料、熔断降级、系统负载保护等维度保证微服务的稳定性。
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数隔离) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 反应时间基于异常比率 |
实现实时统计 | 滑动窗口 | 滑动窗口 | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
支持注释 | 支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式、匀速器模式、预热排队模式 | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用控制台,可配置规则、检查秒监控、机器发现等 | 监控检查简单 | 不提供控制台,可与其他监控系统对接 |
2.2.Sentinel介绍
2.2.1.Sentinel简介
Sentinel 是阿里巴巴出品的面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护等多个维度来保微服务的稳定性。
主页地址:https://github.com/alibaba/Sentinel
- 2012 年,Sentinel 诞生,主要功能为入口流量控制。
- 2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量归整场景以及生产实践。
- 2018 年,Sentinel 开源,并持续演进。
- 2019 年,Sentinel 朝着多语言扩展的方向不断探索,推出 C++ 原生版本,同时针对 Service Mesh 场景也推出了 Envoy 集群流量控制支持,以解决 Service Mesh 架构下多语言限流的问题。
- 2020 年,推出 Sentinel Go 版本,继续朝着云原生方向演进。
Sentinel 的使用主要分为两个部分:
- 核心库:主要指Java 客户端,不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台:控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。
2.2.2.Sentinel特征
Sentinel 具有以下特征:
- :Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- :Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- :Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- :Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
2.2.3.Sentinel特性
2.2.4.Sentinel开源生态
2.2.5.Sentinel的相关概念
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则指的是围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
2.2.6.Sentinel的优势
- 友好的控制面板
- 支持实时监控。
- 支持多种限流。支持QPS限流,线程数限流以及多种限流策略。
- 支持多种降级模式,支持按平均返回时间降级,按多种异常数降级,按异常比率降级等。
- 方便扩展开发,支持SPI模式对chain进行扩展。
- 支持链路的关联,可以实现按链路统计限流,系统保护,热门资源保护等等。
3.Sentinel入门
3.1.Sentinel初体验
为了方便理解Sentinel,Sentinel提供了公网Demo来帮助我们快速熟悉Sentinel,步骤分为两步,具体如下:
- 下载公网Demo
- 开通阿里云AHAS控制台
3.1.1.开通阿里云的AHAS控制台
阿里云的AHAS控制台需要注册登陆到阿里云平台并进行开通才能使用,具体如下:
阿里云地址:https://www.aliyun.com
注册之后需要进行实名认证
如果是个人推荐“个人实名认证”,如果是企业推荐“企业/政府实名认证”。这里选择个人实名认证。
个人实名认证有“个人支付宝授权认证”和“个人扫脸认证”,这里选择“个人支付宝授权认证”,认证速度会比较快。
登录之后,可以进行绑定邮箱,也可以选择暂不绑定。
在阿里云中找到“产品分类”中的"开发与运维"中的”应用高可用服务AHAS“选项
选择“免费开通”。
选择“立即开通”。开通成功之后,点击“管理控制台”,进入管理控制平台。
3.1.2.公网Demo
公网Demo的操作主要分为三步,具体如下:
- 下载公网Demo
- 公网Demo接入阿里云AHAS控制台
- 定义公网Demo的流控规则
在控制台顶部的地域列表中,选择地域为 。
在控制台左侧导航栏选择“流量防护”中的“应用防护”,会弹出应用列表。
点击右侧的“新应用接入”按钮,弹出接入新应用的界面,选择接入语言“Java“,选择接入方式”体验Demo“。
可以根据下面提供的下载Demo包的指令下载公网Demo,通过启动Demo的指令启动公网Demo,之后点击“我已完成上述步骤”按钮,完成公网Demo的接入操作。
公网Demo下载地址:https://ahasoss-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/sdk/latest/ahas-sentinel-sdk-demo.jar
如果没有网络,也可以到课程资料的“资料”目录下的“公网Demo”目录下找到提前准备好的ahas-sentinel-sdk-demo.jar来进行使用。
执行以下指令启动公网Demo
java -Dahas.namespace=default -Dproject.name=SentinelDemo -Dahas.license=f7a69fd45e9d4135884ea1a6554faaa6 -jar ahas-sentinel-sdk-demo.jar
通过阿里云AHAS管理控制平台可以看到如下效果:
在应用列表页面单击流控降级 SentinelDemo 的应用卡片,进入应用概览页面。
在控制台左侧导航栏中单击“监控详情”。在该应用的监控详情页面,单击 function_0 资源卡片右上角的“+”
在新增规则对话框中,设置单机QPS阈值为 10,然后单击新建。
这样流控规则就设置好了,这是在查看function_0的标签,会有以下效果:
返回应用列表页面,查看SentinelDemo应用的情况,会发现多了一个流量控制规则,并且规则生效了
3.2.Sentinel流控降级入门
Sentinel本地应用流控降级实现分为三步:
- 创建本地应用
- 搭建本地Sentinel控制台
- 本地应用接入本地Sentinel控制台
3.2.1.本地应用创建
- 创建springboot项目
- 在项目的pom.xml文件中引入sentinel-core的依赖坐标
- 创建TestController,定义使用限流规则
- 运行测试
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima.sentinel</groupId>
<artifactId>sentinel_quick_start</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sentinel_quick_start</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--sentinel核心依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
单元测试我们不需要,所以将单元测试的依赖坐标和单元测试类删除。
这里我们定义OPS类型的限流规则,每秒可接受的请求最多为2个,超过则返回给页面“系统繁忙,请稍候”,不超过则返回给页面“Hello Sentinel!”。
@RestController
public class TestController {
@GetMapping("hello")
public String hello(){
//1.进行限流控制
try (Entry entry = SphU.entry("Hello")){
//限流入口
return "Hello Sentinel!";//被保护的资源
} catch (BlockException e) {
e.printStackTrace();
return "系统繁忙,请稍候";//被限流或者降级的处理
}
}
/** * 定义限流规则 * @PostConstruct :在构造函数执行完毕后执行 */
@PostConstruct
public void initFlowRules(){
//1.创建存放限流规则的集合
List<FlowRule> rules = new ArrayList<FlowRule>();
//2.创建限流规则
FlowRule rule = new FlowRule();
//定义资源
rule.setResource("Hello");
//定义限流规则类型,RuleConstant.FLOW_GRADE_QPS:OPS类型
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//定义OPS每秒最多只能通过的请求个数
rule.setCount(2);
//将限流规则添加到集合中
rules.add(rule);
//3.加载限流规则
FlowRuleManager.loadRules(rules);
}
}
通过浏览器访问http://localhost:8080/hello,慢速刷新,则持续显示”Hello Sentinel”;快速刷新则会交替出现”Hello Sentinel”和“系统繁忙,请稍候”。这说明对“Hello"资源限流成功。我们还可以通过查看日志获取限流详情,日志文件的位置可以在控制台找到(图中红框处)。
在该目录下找到com-itheima-sentinel-sentinel_quick_start-SentinelQuickStartApplication-metrics.log.yyyy-MM-dd文件,查看该文件内容如下所示:
3.2.2.本地Sentinel控制台搭建
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、实时监控(单机和集群),规则管理和推送的功能。
下载地址:https://github.com/alibaba/Sentinel/releases/download/1.7.2/sentinel-dashboard-1.7.2.jar
启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。
使用如下命令启动控制台:
java -Dserver.port=9000 -jar sentinel-dashboard-1.7.2.jar
通过浏览器打开http://localhost:9000/即可访问Sentinel控制台,默认用户名和密码都是sentinel
但是此时本地应用还没有接入到Sentinel控制台进行管理,所以接下来就要将本地应用接入到Sentinel控制台。
3.2.3.应用接入控制台
本地应用是以客户端的身份来接入控制台,具体步骤如下:
<!--本地应用接入本地控制台的依赖-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.2</version>
</dependency>
:设置Sentinel控制台的主机地址和端口
:设置本地应用在Sentinel控制台中的名称
重启本地应用并重新通过浏览器访问http://localhost:8080/hello,快慢速刷新几次,查看控制台中的实时监控情况。
需要注意的是应用配置好了与控制台的连接参数之后,并不会主动连接上控制台,需要触发一次应用的规则才会开始进行初始化,并向控制台发送心跳和应用规则等信息。
此外还需要注意的是,Sentinel提供了两种设置流控规则的方式
-
在应用中使用代码编写流控规则(案例中使用的方式)
-
在Sentinel控制台设置流控规则
在Sentinel控台的左侧菜单中选择流控规则即可对限流规则进行调整
3.3.Sentinel定义资源的方式
Sentinel除了基本的定义资源的方式之外,还有其他的定义资源的方式,具体如下:
- 抛出异常的方式定义资源
- 返回布尔值方式定义资源
- 异步调用支持
- 注解方式定义资源
- 主流框架的默认适配
3.3.1.抛出异常的方式定义资源
Sentinel中的SphU 包含了 try-catch 风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理,而我们在入门案例中就使用的此种方式进行定义资源,关键代码如下:
try (Entry entry = SphU.entry("Hello")){
//使用限流规则监控保护资源
return "Hello Sentinel!";//被保护的资源
} catch (BlockException e) {
e.printStackTrace();
return "系统繁忙,请稍候";//被限流或者降级的处理
}
3.3.2.返回布尔值方式定义资源
Sentinel中的SphO 提供 if-else 风格的 API。用这种方式,当资源发生了限流之后会返回 false
,这个时候可以根据返回值,进行限流之后的逻辑处理。
1.在sentinel_quick_start项目中创建TestBooleanController,在TestBooleanController中使用返回布尔值的方式定义资源
@RestController
public class TestBooleanController {
@GetMapping("boolean")
public boolean hello() {
//1..进行限流控制
if (SphO.entry("Sentinel_Boolean")) {
//限流入口
try {
//被保护的资源
System.out.println("访问成功");
return true;
} finally {
//SphO.entry(xxx)需要与 SphO.exit()方法成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException异常
SphO.exit();//限流出口,
}
} else {
//被限流或者降级的处理
System.out.println("系统繁忙,请稍候");
return false;
}
}
}
SphO.entry(xxx)需要与 SphO.exit()方法成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException异常。
2.运行测试
在Sentinel控制的中增加关于“Sentinel_Boolean”资源的流控规则
通过浏览器访问http://localhost:8080/boolean,慢速刷新,则持续显示”true”;而Idea打印台显示“访问成功”,快速刷新则会交替出现“true”和“false”,打印台则会交替出现“访问成功”和“系统繁忙,请稍候”,这说明使用返回布尔值方式对“Sentinel_Boolean"资源限流成功。
3.3.3.异步调用支持
Sentinel 支持异步调用链路的统计。在异步调用中,需要通过 SphU.asyncEntry(xxx) 方法定义资源,并通常需要在异步的回调函数中调用 exit 方法。
1.在本地应用的引导类中添加@EnableAsync,表示springboot项目开始异步调用支持
@SpringBootApplication
@EnableAsync
public class SentinelQuickStartApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelQuickStartApplication.class, args);
}
}
2.创建AsyncService编写异步调用的方法
@Service
public class AsyncService {
//@Async表示方法为异步调用方法
@Async
public void hello(){
System.out.println("异步开始-----");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("完成异步----");
}
}
3.创建TestAsyncController,实现异步调用限流控制
@RestController
public class TestAsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("async")
public void hello() {
//1.进行限流控制
AsyncEntry asyncEntry = null;
try {
asyncEntry = SphU.asyncEntry("Sentinel_Async");//限流入口
asyncService.hello();//异步方法调用
} catch (BlockException e) {
//被限流或者降级的处理
System.out.println("系统繁忙,请稍候");
}finally {
if (asyncEntry != null){
asyncEntry.exit();//限流出口,
}
}
}
}
4.运行测试
在Sentinel控制的中增加关于“Sentinel_Async”资源的流控规则
通过浏览器输入http://localhost:8080/async,慢速刷新,查看Idea的打印台,会发现打印台会打印出“异步开始-”;快速刷新可以查看Idea的打印台,则会发现打印台会交替打印出“异步开始”和“系统繁忙,请稍候”,这也说明对“Sentinel_Boolean"资源限流成功。
3.3.4.注解方式定义资源
Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler函数来进行限流之后的处理。
1.在本地应用的pom.xml文件中引入依赖
因为Sentinel中使用AspectJ 的扩展用于自动定义资源、处理 BlockException 等,所以需要在项目中引入sentinel-annotation-aspectj依赖。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.7.2</version>
</dependency>
2.创建AspectJ 的配置类
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
3.创建TestAnnController,实现限流控制
@RestController
public class TestAnnController {
//定义限流资源和限流讲解回调函数
@SentinelResource(value = "Sentinel_Ann", blockHandler = "exceptionHandler")
@GetMapping("ann")
public String hello() {
return "Hello Sentinel!";
}
// blockHandler函数,原方法调用被限流/降级/系统保护的时候调用
public String exceptionHandler(BlockException ex) {
ex.printStackTrace();
return "系统繁忙,请稍候";
}
}
- @SentinelResource 注解用来标识资源是否被限流、降级。上述例子中该注解的属性 ‘Sentinel_Ann’ 表示资源名。
- @SentinelResource 还提供了其它额外的属性如 blockHandler来指定被限流后的操作。
4.运行测试
在Sentinel控制的中增加关于“Sentinel_Ann”资源的流控规则
通过浏览器输入http://localhost:8080/ann,慢速刷新,则持续显示”Hello Sentinel”;快速刷新则会交替出现”Hello Sentinel”和“系统繁忙,请稍候”。这说明对“Sentinel_Ann"资源限流成功。
3.3.5.主流框架的默认适配
为了减少开发的复杂程度,我们对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了适配。您只需要引入对应的依赖即可方便地整合 Sentinel。
4.Sentinel高级
4.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-starter-alibaba-sentinel依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2.在项目中创建TestController
@RestController
public class TestController {
//定义限流资源和限流讲解回调函数
@SentinelResource(value = "Sentinel_SpringCloud", blockHandler = "exceptionHandler")
@GetMapping("ann")
public String hello() {
return "Hello Sentinel!";
}
// blockHandler函数,原方法调用被限流/降级/系统保护的时候调用
public String exceptionHandler(BlockException ex) {
ex.printStackTrace();