SpringCloud Alibaba实战--第五篇:Sentinel Ⅰ安装入门及流控
系列文章目录
微服务新王SpringCloudAlibaba
文章目录
- 系列文章目录
- 前言
- Sentinel: 分布式系统的流量防卫兵
- 一、与Hystrix的对比
-
- 1. Hystrix
- 2. Sentinel
- 二、Sentinel的下载与安装
-
- 1. 下载
- 2. 怎么玩
- 三、初始化演示工程
-
- 1. 创建8401工程
- 2. 启动测试
- 四、Sentilnel流量限制控制规则
-
- 1. 流控模式的基本介绍
- 2.流控模式之 直接限流之QPS(默认)
- 3. 流控模式之直接限流之线程数
- 4. 流控模式之关联
- 5. 流控模式之链路
- 五、流控效果
-
- 1. 快速失败
- 2. 预热(Warm Up)
- 3. 排队等待
- 六、总结
前言
Sentinel: 分布式系统的流量防卫兵
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
- 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
- 官方文档:https://github.com/alibaba/Sentinel
- 中文文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
- sentinel与hystrix功能类似,但是更优。
一、与Hystrix的对比
1. Hystrix
- 需要我们自己手动搭建平台。
- 没有一套web页面可以给我们进行更加细粒度的配置。
- 流量控制、速率控制、服务熔断、服务降级…
2. Sentinel
- 单独一个组件,可以独立出来。
- 支持界面化的细粒度统一配置。
- 抄的Hystrix作业,理念都是一致的,只不过后来者肯定功能更丰富、更好用。
- 注解>配置>编码,我们主要以注解和配置的方式来学习Sentinel。
二、Sentinel的下载与安装
1. 下载
下载地址:https://github.com/alibaba/Sentinel/releases/tag/1.7.0
参照博客:https://xiaozhang.blog.csdn.net/article/details/122557207
(外网网速太慢,请参照博客使用相关工具下载)
下载1.7.0的版本
2. 怎么玩
- 官网说明:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel
- sentinel组件由2部分构成,后台和前台8080
- 基于SpringBoot框架开发,默认端口8080,使用java命令即可启动。
java -jar sentinel-dashboard-1.7.0.jar
- 访问页面,默认用户名密码都是sentinel,成功进入即代表安装完成
http://localhost:8080/#/login
三、初始化演示工程
1. 创建8401工程
模块名
cloudalibaba-sentinel-service8401
pom.xml,其中以下部分添加的是微服务nacos+sentinel+openfeign
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2021</artifactId> <groupId>com.atguigu.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloudalibaba-sentinel-service8401</artifactId> <dependencies> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.3</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies></project>
application.yml
server: port: 8401spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 #Nacos服务注册中心地址 sentinel: transport: dashboard: localhost:8080 #配置Sentinel dashboard地址#默认端口8719,假如被占用会自动+1直到找到可用端口 port: 8719management: endpoints: web: exposure: include: '*'
基础包
com.atguigu.springcloud.alibaba
主启动类MainApp8401
package com.atguigu.springcloud.alibaba;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/** * @auther zzyy * @create 2020-02-24 16:26 */@EnableDiscoveryClient@SpringBootApplicationpublic class MainApp8401{ public static void main(String[] args) { SpringApplication.run(MainApp8401.class, args); }}
测试流量控制接口FlowLimitController
package com.atguigu.springcloud.alibaba.controller;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;/** * @auther zzyy * @create 2020-02-24 16:26 */@RestController@Slf4jpublic class FlowLimitController{ @GetMapping("/testA") public String testA() { return "------testA"; } @GetMapping("/testB") public String testB() { log.info(Thread.currentThread().getName()+"\t"+"...testB"); return "------testB"; }}
2. 启动测试
启动nacos、sentinel及8401工程
登录sentinel,看是否已经监控到8401工程,默认账号密码都是sentinel
http://localhost:8080/
哎!空空如也~
原来sentinel用的是懒加载机制,当监控的微服务有被访问之后才会出现监控信息,我们访问下8401的接口
http://localhost:8401/testA
http://localhost:8401/testB
再次刷新sentinel页面,微服务已被监测
查看实时监控页面,我们多刷新几次两个接口
四、Sentilnel流量限制控制规则
1. 流控模式的基本介绍
- 资源名:唯一名称,默认请求路径。
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
- 阀值类型/单机阈值:
- QPS(每秒钟的请求数量):当调用该QPS达到阈值的时候,进行限流
- 线程数:当调用该API的线程数达到阈值的时候,进行限流
- 是否集群:不需要集群。
- 流控模式:
- 快速失败:直接失败,抛异常。
- Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/coderFactor,经过预热时长,才达到设置的QPS阈值。
- 排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效。
看了以上这么灵活的配置,是不是被秀翻了?
我们一个一个来尝试一下。
2.流控模式之 直接限流之QPS(默认)
我们测试下添加流量控制规则,使用默认的直接限流+快速失败(前提是我们的服务啥的都启动着)。
测试给/testA接口添加流量控制。
点击新增,新增成功后我们能在流控规则页面看到对应的规则。
这时,再测试访问testA接口,我们先访问慢一点,不让他达到阈值。
http://localhost:8401/testA
接口是正常的。
接着,我们狂点几次,发现流量已经被限制,请求不到接口信息了。
流量被Sentinel阻塞(限流)。
留下一个问题:直接调用了默认的报错信息,但是是否应该有一个类似于Hystrix的fallback方法让我们做后续业务处理?
当然,我们后面再说。
3. 流控模式之直接限流之线程数
修改testA配置的限流规则
修改testA接口的代码,请求过来后让线程睡眠三秒,以达到我们的测试效果。(注意:项目重启后由于项目从sentinel中注销,需要重新配置规则)
@GetMapping("/testA")public String testA(){ try { TimeUnit.MILLISECONDS.sleep(3000); log.info(Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } return "------testA";}
好,接下来我们访问testA接口,先访问一次,会发现在转圈圈,接着多次访问,会发现报错。
这里说下原因,SpringBoot内置的还是tomcat,tomcat中Servalet会给每个请求开一个线程来处理(异步的),当我们多次访问时就触发了多个线程,我们代码中让线程睡了3秒(模拟处理3秒),这样就表示一个请求处理完前其他线程不会被处理而是直接报错。
这里我们思考一下:为什么要区分QPS和线程数限流呢?
很简单,我们想一下,QPS的原理是直接将请求阻断掉不让他请求到接口,而线程数限流是让请求进入接口,超出线程数量后才让他失败,比如我们的一个接口如果响应比较慢,我们可以使用线程限流,而QPS是为了更好的防止系统被流量压垮的策略,这也是根据业务场景不同来选择的(这里说句阿里牛逼,不过也可以理解,比较业务场景多)。
QPS达到阈值后所有请求都不接收了。
线程模式达到阈值后仍然接收,超出线程数量了就不处理。
根据不同的业务场景我们能选择这两种不同的限流规则,如秒杀、抢消费券等业务场景,我们可以使用QPS限流,限制接口访问次数,而对于接口逻辑复杂、处理较慢的接口我们可以选择线程模式,实在干不过来了就不处理。
4. 流控模式之关联
当关联资源达到阈值时,就限流自己。
把后台的testA的睡眠先去掉。
如A接口调用的有B接口,然后B接口达到配置的关联规则了,我们对A进行限流,当业务产生关联时我们通常使用这种方式以防止系统崩溃情况的恶化。
配置testA接口关联testB接口。
点击保存,这个配置的意思就是当我们的testB的QPS达到每秒1次时,我们的testA就不能访问了。
接下来,使用postMan进行循环访问testB,进行测试。
postman安装及使用:https://blog.csdn.net/weixin_43464964/article/details/121999824?spm=1001.2014.3001.5501
这样我们就配置好了,先别急着发送,我们先测试下A,狂刷testA,发现一直都正常。
然后我们启动postman刷testB接口,再访问testA,发现已经被sentinel限流。
5. 流控模式之链路
链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流。它的功能有点类似于针对来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度更细。
以调用链路为单位做限流处理,例如:A->B->C 这个链路的总体流量只按入口A的请求量来计算。
这个可以自行尝试下测试。
https://blog.csdn.net/qq_29064815/article/details/107102060?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164258906116780271539848%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164258906116780271539848&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-5-107102060.pc_search_insert_ulrmf&utm_term=sentinel%E7%9A%84%E9%93%BE%E8%B7%AF%E6%A8%A1%E5%BC%8F%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8&spm=1018.2226.3001.4187
五、流控效果
1. 快速失败
快速失败:直接失败,抛异常,也是默认的方式。
2. 预热(Warm Up)
公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值
默认coldFactor为3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
关于冷启动的说明:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81—%E5%86%B7%E5%90%AF%E5%8A%A8
预热效果配置:
该配置表示的是:默认 coldFactor 为 3,即请求QPS从(threshold / 3) 开始,经多少预热时长(5秒)才逐渐升至设定的 QPS 阈值。案例,阀值为10+预热时长设置5秒。系统初始化的阀值为10 / 3 约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10。效果就是我们均匀的点击,一开始超过一秒3次会直接失败,然后慢慢的到5秒时只要不超过一秒10次就不会失败。
添加后可以狂点testA接口刷新,会发现刚开始会出现失败,过几秒后就不会出现失败了。
应用场景如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值。
在实时监控页面中也可以看到该信息。
3. 排队等待
匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。
官网的说明:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
应用场景:主要用于处理间隔性的突发的流量,例如消息队列。在某一秒有大量的请求到来,而接下来几秒则处于空闲状态,我们希望系统能够在接下来空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
修改testA接口,查看打印效果。
@GetMapping("/testA")public String testA(){ log.info(Thread.currentThread().getName()+"\t ...testA"); return "------testA";}
使用postman进行测试
可以把时间改短一点再测试一下,会发现效果照旧O(∩_∩)O
六、总结
- Sentinel是类似与Hystrix的微服务流量控制及服务降级、熔断组件。
- 通过页面可以灵活的针对监控微服务进行流量控制。
- Sentinel是懒加载模式,只有被调用过的微服务才会被监控到。
- 资源名:唯一名称,默认请求路径。
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
- 阀值类型/单机阈值:
- QPS(每秒钟的请求数量):当调用该QPS达到阈值的时候,进行限流
- 线程数:当调用该API的线程数达到阈值的时候,进行限流
- 流控模式:
- 直接:当API达到限流条件时,直接进行限流。
- 关联:当关联资源达到阈值时,就限流自己。
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【API级别的针对来源】。
- 流控效果:
- 快速失败:直接失败,抛异常。
- Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/coderFactor,经过预热时长,才达到设置的QPS阈值。
- 排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效。