SpringCloud中使用Sentinel实现限流的实战
作者:蹊源的奇思妙想
前言
在分布式的项目中经常会遇到那种高并发的场景,为了保证系统不会被突然激增的请求导致宕机,我们常常会使用一种服务降级的手段来保护我们的系统,本篇博客将介绍如何使用SpringCloud
中使用Sentinel
实现限流,从而达到服务降级的目的。
正文 Sentinel
Sentinel 是面向微服务的轻量级流量控制框架,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel可以作为Hystrix
的替代品,为系统提供服务熔断和服务降级的功能。
- 服务熔断:根据保险丝的熔断是一个原理,当调用目标服务大量超时和失败,这时候应该熔断掉该服务的调用,从而快速释放资源,这段时间所有对其调用都是快速返回,保证整体服务系统的稳定
- 服务降级:针对核心业务服务的压力剧增,根据当前业务场景和流量对其他非核心服务进行降级处理,可以进行限流,快速返回等处理,释放资源保证核心任务的正常运行。
Sentinel的限流原理
Sentinel
以Bucket
(桶)为单位记录一个时间窗口内的请求总数、异常总数、总耗时等指标数据。- 而一个
Bucket
可以是记录一秒内的数据,也可以是10毫秒内的数据,我们称这个时间窗口为Bucket
的统计单位,由使用者自定义。
所以Sentinel
是基于滑动窗口算法来实现的。
设置Sentinel的阈值指标:
线程数模式
线程数的模式采用信号隔离的方式来防止线程池被占用。
用于防止线程池被占用,一般有两种方式:
- 线程池隔离:为应对太多线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢,这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的
overhead
比较大,特别是对低延时的调用有比较大的影响。 - 信号隔离:
sentinel
采用的是信号隔离的方案,简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝。
所以业务处理是多线程的情况下使用线程数模式。
Sentinel
采用信号隔离的方式,通过并发线程数模式,并结合基于响应时间的熔断降级模式,可以在不稳定的平均相应时间比较高的时候自动降级,防止过多的慢调用占满并发数,影响整个系统,避免慢调用引起依赖雪崩的现象。
QPS模式QPS
即每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。QPS
模式适合单读线程情况(如servlet
请求),这种模式下提供了三种更加精确的流控方式:
- 直接拒绝 :直接失败
- Warm Up: 即请求
QPS
从threshold / 3
开始,经预热时长逐渐升至设定的QPS
阈值,通常用于秒杀系统。 - 匀速排队:设置一个等待时间, 匀速处理请求,保证服务的均匀性,不能处理
QPS>1000
的场景。
Sentinel 两种计算阈值的模式:
- 集群总体模式:即限制整个集群内的某个资源的总体
qps
不超过此阈值。 - 单机均摊模式:单机均摊模式下配置的阈值等同于单机能够承受的限额,
token server
会根据连接数来计算总的阈值(比如独立模式下有 3个client
连接到了token server
,然后配的单机均摊阈值为 10,则计算出的集群总量就为30),按照计算出的总的阈值来进行限制。这种方式根据当前的连接数实时计算总的阈值,对于机器经常进行变更的环境非常适合。
这里要说明的是:qps
是每秒查询数, tps
是每秒内的事务数, pv
是指页面被浏览的次数。
Sentinel流控模式
- 直接模式: 接口达到限流条件时,开启限流
- 关联模式: 当关联的资源达到限流条件时,开启限流
- 链路模式:当从某个接口过来的资源达到限流条件时,开启限流
Sentinel限流的方式
- 在
Sentinel
控制台中根据url
进行限流设置 - 通过注解的方式进行自定义限流,又可以分为:自定义
url
限流和自定义资源限流。
第一步:部署sentinel-dashboard
sentinel-dashboard(点击下载jar
包)是一个单独的应用,通过spring-boot
进行启动,主要提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。
这里可以理解为sentinel
服务治理中心。
java -Dserver.port=18080 -jar sentinel-dashboard.jar
第二步:在项目中整合sentinel
注入依赖
<!--springCloud-Alibaba--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--sentinel限流--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.1.RELEASE</version> </dependency>
在application.properties中的相关配置
spring.application.name=imagerepair server.port=8080 spring.cloud.sentinel.transport.dashboard=127.0.0.1:18080 spring.cloud.sentinel.eager=true
Controller层
@RestController public class UserController { @Autowired UserService userService; @RequestMapping("/hello") public String hello(){ return userService.sayHello(); } }
Service
@Service public class UserService { @SentinelResource(value = "sayHello",fallback = "sayHellofail") public String sayHello(){ return "Hello,World"; } public String sayHellofail(){ return "I'am sorry"; } }
设置限流,快速访问,从而触发服务降级
设置Sentinel的资源
当请求超过设定的阈值,启动限流降级,展示如下:
项目源码
该项目源码可从我的github中获取。
到此这篇关于SpringCloud中使用Sentinel实现限流的实战的文章就介绍到这了,更多相关SpringCloud Sentinel限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!