Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(二))(JMeter模拟测试)

简介: Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(JMeter模拟测试)(二)

四. Sentinel普通流控

1. 普通流控定义

/**

* flow 流控规则,详情查看RuleType

*/

FLOW("flow", FlowRule.class)


作用在网关的流控称之为网关流控,相对的作用在除网关之外的微服务流控这里称为普通流控


在上一个章节中,发现网关流控并不是万能的,像认证中心youlai-auth调用系统服务youlai-admin这种微服务相互调用而不走网关的情况,网关流控表示无能为力,但不可否认的是网关流控确实能够应对大多数场景的流控。


所以在像上文中的网关流控无能为力的案例,则需要普通流控的救场。


2. 普通流控的规则

Field 说明 默认值

resource 资源名,资源名是限流规则的作用对象

count 限流阈值

grade 限流阈值类型,QPS 【1】或线程数模式【0】 QPS 模式

limitApp 流控针对的调用来源 default,代表不区分调用来源

strategy 判断的根据是资源自身,还是根据其它关联资源 (refResource),还是根据链路入口 根据资源本身

controlBehavior 流控效果(直接拒绝 / 排队等待 / 慢启动模式) 直接拒绝

3. 导入依赖

com.alibaba.cloud

spring-cloud-starter-alibaba-sentinel


com.alibaba.csp

sentinel-datasource-nacos



4. 微服务配置

spring:

 application:

   name: youlai-admin

 cloud:

   nacos:

     discovery:

       server-addr: http://localhost:8848

     config:

       server-addr: ${spring.cloud.nacos.discovery.server-addr}

       file-extension: yaml

   sentinel:

     enabled: true

     eager: true # 取消控制台懒加载,项目启动即连接Sentinel

     transport:

       client-ip: localhost

       dashboard: localhost:8080

     datasource:

       # 限流规则,flow为key,随便定义

       flow:

         nacos:

           server-addr: ${spring.cloud.nacos.discovery.server-addr}

           dataId: ${spring.application.name}-flow-rules

           groupId: SENTINEL_GROUP

           data-type: json

           rule-type: flow


5. Nacos添加流控规则

进入Nacos控制台,添加规则配置文件,接着上文的案例,在认证的时候,youlai-auth需通过feign调用youlai-admin根据用户名获取用户信息。

微信图片_20230710074742.png



进入Sentinel控制台查看,除了刚在Nacos添加的规则之外,还可以看到普通流控面板和网关流控面板的区别

微信图片_20230710074745.png



6. 普通流控测试

经过网关流控限制只能有10条请求到youlai-auth,接下来youlai-auth调用youlai-admin链路中,因为限制了youlai-admin的QPS上限为5,所以最终应该是只有5条请求是有效的。看测试结果:

微信图片_20230710074749.png微信图片_20230710074752.png





7. 自定义异常

上面被限流后的异常信息,显然不是想要的,那么如何自定义普通流控异常呢?


**解决方案:**实现BlockExceptionHandler接口


@Component

public class DefaultBlockExceptionHandler implements BlockExceptionHandler {

   @Override

   public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {

       response.setStatus(HttpStatus.ok().status());

       response.setCharacterEncoding("UTF-8");

       response.setContentType("application/json;charset=utf-8");

       if(e instanceof FlowException){

           // objectMapper.writeValue 用于将java对象转位JSON格式返回调用方

           new ObjectMapper().writeValue(response.getWriter(), Result.failed(ResultCode.FLOW_LIMITING));

       }

   }

}


为了测试普通流控,首先关闭网关流控,排除一些异常干扰


微信图片_20230710074836.png


添加获取当前登录用户信息的HTTP请求


微信图片_20230710074839.png


因为此HTTP接口需要认证,所以需要在请求头添加token。鼠标右击HTTP请求->添加->配置元件->HTTP信息头管理

微信图片_20230710074842.png



HTTP信息头管理器添加token

微信图片_20230710074909.png



执行线程组,查看自定义异常生效

微信图片_20230710074911.png



五. Sentinel熔断降级

1. 熔断降级概述

微服务架构都是分布式的,不同服务相互调用,组成复杂的调用链路。复杂的链路上某一环不稳定,就可能层层级联,最终导致整个链路都不可用。因此需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定的调用,避免局部不稳定因素导致正题的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。


2. 熔断策略

微信图片_20230710074937.png


Sentinel提供了三种熔断策略:


慢调用比例: 请求响应时间大于设置的RT(即最大的响应时间)则统计为慢调用。触发此熔断策略的条件需要满足两个条件,一是单位统计时长(statIntervalMs)内请求数大于设置的最小请求数,二是慢调用的比例大于阈值,接下来在熔断时长的范围内请求会自动的被熔断。过了熔断时长后,熔断器进入探测恢复状态(HALF-OPEN状态),若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断。

异常比例:当单位统计时长请求数大于设置的最小请求数,并且异常的比例大于阈值,则接下来的熔断时长内请求会被自动熔断。

异常数:当单位统计时长内的异常数目超过阈值之后会自动进行熔断。

3. 熔断降级规则

熔断降级规则(DegradeRule)包含下面几个重要的属性:


Field 说明 默认值

resource 资源名,即规则的作用对象

grade 熔断策略,支持慢调用比例/异常比例/异常数策略 慢调用比例

count 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值

timeWindow 熔断时长,单位为 s

minRequestAmount 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) 5

statIntervalMs 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) 1000 ms

slowRatioThreshold 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

4. 微服务配置

spring:

 cloud:

   sentinel:

       # 降级规则,degrade为降级key,随便取名

       degrade:

         nacos:

           server-addr: ${spring.cloud.nacos.discovery.server-addr}

           dataId: ${spring.application.name}-degrade-rules

           groupId: SENTINEL_GROUP

           data-type: json

           rule-type: degrade


5. Nacos添加熔断降级规则

微信图片_20230710074948.png


方便看到异常熔断的效果,选择了异常数的熔断策略,毕竟数数比计算比例简单多了。资源名为getCurrentUser是怎么回事,不急下文提到。总之这里的配置的大概意思就是说针对getCurrentUser资源,如果请求该接口出现了异常,则进行熔断,熔断时长为5秒。


6. 熔断异常模拟

先模拟一段在运行时发生异常的代码,在获取当前登录用户信息的接口埋个雷吧,注意到@SentinelResource注解中的value值getCurrentUser,也就是资源名称,联系上文,降级规则就是针对这个接口的方法。和上面在普通流控测试使用的是请求的路径不同,这里显示指定了资源名称和降级规则配置去做匹配。


微信图片_20230710075005.png


@SentinelResource注解中的属性除了定义资源名的属性值value,还有两个属性有关降级处理分别是blockHandlerClass和blockHandler。意思是在单位时间接口异常数超过设置的阈值后进入熔断,在熔断时长(上面降级规则中设置的是5秒)范围内,再有请求过来访问该接口时,不会再走接口方法体内的逻辑。因为前面几次接口出现异常,那么敢断定接下来短时间内大概率还是会发生异常,所以索性就把后续的请求拦截避免,这也是熔断的意义。


在5秒的熔断时长内,如果再有请求访问该接口则会走降级的逻辑,也就是上图中指定的UserBlockHandler#handleGetCurrentUserBlock降级处理方法。


微信图片_20230710075040.png


7. 熔断降级测试

在测试前,需要关闭网关那边流控,排除一些异常情况下的干扰。还有为了方便在JMeter查看结果,临时关闭全局异常处理器GlobalExceptionHandler。


还是拿上一节配置好的测试普通流控的线程组,获取登录用户的信息来作为熔断降级的测试案例,先看一下线程组的设置:


线程数为10,达到了熔断降级最小请求数(规则配置的5)的要求


微信图片_20230710075053.png


获取登陆用户信息的接口信息

微信图片_20230710075056.png



请求头添加token

微信图片_20230710075101.png



测试线程组配置好之后看看使用不使用熔断降级和使用熔断降级的区别:


不使用熔断降级

配置中关闭Sentinel


sentinel:

 enabled: false

1

2

微信图片_20230710075124.png微信图片_20230710075134.png




发现了吗?这种请求异常处理模式头铁啊,即使撞了南墙也不会回头,下次继续撞,下下次继续撞。ok,你没关系,那你有考虑一直被你撞的墙(服务器)了没?


使用熔断降级

配置中开启Sentinel


sentinel:

 enabled: true

1

2

微信图片_20230710075153.png微信图片_20230710075156.png




通过日志可以看到进入主线代码的只有一次,后续的请求直接进入降级支线。

微信图片_20230710075215.png



过了熔断时长5秒后,熔断器进入探测恢复状态(HALF-OPEN状态),这时候如果一个请求到主线没异常,关闭熔断器,让后续的请求都到主线过来;如果还是异常,打开熔断器。


六. Sentinel整合Feign熔断降级

1. Feign与Sentinel整合意义

在微服务架构中,声明式调用Feign在微服务之间调用充当重要的角色,在使用Feign的过程中如果为了系统的健壮性,一定会考虑如果因目标服务异常调用失败后的处理。


说到这里,相信对微服务有些了解的童鞋对下面的代码很熟悉:

微信图片_20230710075231.png微信图片_20230710075234.png





上面两张图反应了Feign客户端在远程调用目标服务失败后,继而选择了降级的逻辑,像做人一样随时要给自己留一条后路,也就是稳,折射到程序亦是如此。这里只是一个降级的自定义异常返回,实际情况根据业务而定。


看到上面的代码,Feign在设计上就支持了降级的处理。这时候相信大家都会有一个疑问,Feign本身已经支持降级,那还需要Sentinel做什么?


换句话说可能会好理解一点,Sentinel给Feign带来了什么好处?


这个问题其实不难理解,先直接从字面上切入。


Feign是能够做到降级,Sentinel能够实现熔断降级,突显出来也就是熔断这一词,其中熔断的具体表象是怎样的?举个栗子说明:


假如客户端a通过feign调用b服务100次,此时b服务故障


没有熔断


a的第1次请求走到b服务跟前,看着b躺在地上没动静,响应给客户端a说b没动静,让客户端a自己看着办吧。后面如此往复99次,每次a都需要走到b的面前然后再响应给客户端a,并告知b故障了。


有熔断


a的第1次请求走到b服务跟前,看着b躺在地上没动静,这时候a就比较机智,判断b服务没有一时半刻是起不来了,就响应给客户端a并说这一时半刻钟的请求你自己看着处理吧,没有必要再到b面前,后面的99次请求就不会再到服务b那里了,省时省力。


想通过上面的举例说明熔断的意义和作用,因为Feign已经支持了降级,那再搭配上Sentinel的熔断,岂不是如虎添翼?


接下来将通过有来项目中的实例,认证中心【youlai-auth】在登录时需要远程feign调用系统服务【youlai-admin】的根据用户名获取用户信息的接口,来说明Sentinel如何整合Feign实现熔断降级及熔断降级的魅力。


2. 导入依赖

youlai-auth添加Sentinel和Nacos持久化规则依赖


   com.alibaba.cloud

   spring-cloud-starter-alibaba-sentinel


   com.alibaba.csp

   sentinel-datasource-nacos




3. 微服务配置

youlai-auth开启Feign对Sentinel的支持


spring:

 application:

   name: youlai-auth

 cloud:

   sentinel:

     enabled: true

     eager: true # 取消控制台懒加载,项目启动即连接Sentinel

     transport:

       client-ip: localhost

       dashboard: localhost:8080

     datasource:

       # 降级规则

       degrade:

         nacos:

           server-addr: ${spring.cloud.nacos.discovery.server-addr}

           dataId: ${spring.application.name}-degrade-rules

           groupId: SENTINEL_GROUP

           data-type: json

           rule-type: degrade

# Feign开启对Sentinel支持

feign:

 sentinel:

   enabled: true



4. 熔断降级规则

在Nacos控制台添加youlai-auth的降级规则


微信图片_20230710075255.png


[

{

 "resource": "GET:http://youlai-admin/api.admin/v1/users/username/{username}",

 "grade": 2,

 "count": 1,

 "timeWindow": 5

}

]


注意资源名称的生成规则,上面配置的意思是如果单位时间内出现了1次异常数,那没接下来5秒的时间窗口范围内的请求,因为熔断器打开,请求直接走降级逻辑。


5. 熔断降级测试

首先要模拟系统服务的根据用户名获取用户信息的接口异常,具体如下图:

微信图片_20230710075300.png



配置JMeter线程组,单位时间1s内执行10个请求,具体配置在普通流控有说明,这里不做赘述。

/微信图片_20230710075303.png



结果在youlai-auth确实执行了10次请求,因为目标服务的异常走了降级的逻辑

微信图片_20230710075306.png



但是真正进入youlai-admin的根据用户名获取用户信息的接口方法却只有1次,后续的9次请求直接走feign客户端的降级逻辑


微信图片_20230710075340.png


上面的测试结果验证了Feign整合Sentinel之后实现了熔断和降级,至此Feign不再孤军奋战。


七. 结语

本文就Sentinel的流控、熔断降级从实战的角度去逐一验证。网关流控、普通流控能够在有限的资源能力保障系统的稳定运行,熔断降级能够在系统故障时提供兜底的处理逻辑保证系统的健壮性,支持降级的Feign整合Sentinel之后get到熔断的技能,至此熔断降级双剑合璧。


以前觉得微服务的限流、熔断降级是可有可无的存在,所以在开源项目中一直迟迟没有做相关的整合,当真正理解这其中的利害关系之后,微服务离不开这些。


当然本文提到的Sentinel功能的冰山一角,像限流延伸的还有热点key、IP限流、参数限流等等,具体选择使用根据场景,功能丰富,总会有你需要的。而且容易上手,是一个很不错的框架,内部的实现原理和还有算法很有必要去了解深入下。


如果有问题,欢迎加我微信(微信号:haoxianrui)


八. 附录

本文涉及的源码地址:


平台 地址

github https://github.com/hxrui/youlai-mall

gitee https://gitee.com/youlaitech/youlai-mall

文中的Sentinel规则配置已放置在项目document/nacos/SENTINEL_GROUP.zip,导入到Nacos控制台即可


微信图片_20230710075353.png


当然你也可以本地启动Sentinel控制台,已经把官方的jar包放置在项目youlai-middleware/setinel/sentinel-dashboard-1.8.1.jar


cd youlai-middleware/setinel

java -jar sentinel-dashboard-1.8.1.jar

1

2

微信图片_20230710075356.png


本地访问 http://localhost:8080即可进入Sentinel控制台



相关文章
|
6月前
|
Java UED Sentinel
微服务守护神:Spring Cloud Sentinel,让你的系统在流量洪峰中稳如磐石!
【8月更文挑战第29天】Spring Cloud Sentinel结合了阿里巴巴Sentinel的流控、降级、熔断和热点规则等特性,为微服务架构下的应用提供了一套完整的流量控制解决方案。它能够有效应对突发流量,保护服务稳定性,避免雪崩效应,确保系统在高并发下健康运行。通过简单的配置和注解即可实现高效流量控制,适用于高并发场景、依赖服务不稳定及资源保护等多种情况,显著提升系统健壮性和用户体验。
117 1
|
6月前
|
Java UED 开发者
Spring Boot 降级功能的神秘面纱:Hystrix 与 Resilience4j 究竟藏着怎样的秘密?
【8月更文挑战第29天】在分布式系统中,服务稳定性至关重要。为应对故障,Spring Boot 提供了 Hystrix 和 Resilience4j 两种降级工具。Hystrix 作为 Netflix 的容错框架,通过隔离依赖、控制并发及降级机制增强系统稳定性;Resilience4j 则是一个轻量级库,提供丰富的降级策略。两者均可有效提升系统可靠性,具体选择取决于需求与场景。在面对服务故障时,合理运用这些工具能确保系统基本功能正常运作,优化用户体验。以上简介包括了两个工具的简单示例代码,帮助开发者更好地理解和应用。
133 0
|
2月前
|
监控 API 开发者
Sentinel:微服务的全能守护
Sentinel 是阿里巴巴开源的一款轻量级流量控制和熔断降级框架。它通过设置流量控制、熔断降级和系统保护规则,确保微服务在高并发场景下稳定运行。Sentinel 提供丰富的功能、实时监控和灵活的集成方式,适用于各种分布式系统。
202 0
|
2月前
|
监控 Java Sentinel
Hystrix 与 Sentinel 大比拼:微服务稳定性工具谁更优?
Hystrix 和 Sentinel 是用于微服务架构中保护服务稳定性和可靠性的工具,主要实现服务熔断、限流、降级等功能。Hystrix 侧重于熔断器模式和服务隔离,通过线程池或信号量隔离服务,防止故障扩散;Sentinel 则更全面,涵盖流量控制、熔断降级和系统自适应保护,适用于高并发场景,并提供实时监控和灵活的策略调整。两者设计理念不同,Hystrix 适合中小规模应用,而 Sentinel 更适合大规模高并发系统。
47 0
|
5月前
|
Java 数据中心 Sentinel
spring boot sentinel 的使用
要实现Spring Boot集成Sentinel的熔断降级,需引入Sentinel依赖并配置Dashboard地址;使用`@SentinelResource`注解定义受保护资源及blockHandler处理降级逻辑;通过Sentinel Dashboard配置熔断规则,如异常比例或响应时间。启动应用后,测试熔断功能,确保Sentinel正常工作。建议动态调整规则以提升系统稳定性。
109 3
|
5月前
|
Java API 开发者
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
892 0
|
7月前
|
Java Sentinel Spring
spring boot 整合 sentinel
spring boot 整合 sentinel
85 1
|
7月前
|
监控 Java 开发者
Spring Cloud中的服务熔断与降级
Spring Cloud中的服务熔断与降级
|
8月前
|
XML 缓存 Java
Spring Boot 优雅实现降级功能:Hystrix 与 Resilience4j 的实践
【6月更文挑战第19天】在分布式系统中,服务降级是一种重要的容错机制。当某个服务不可用或响应慢时,降级机制可以保证系统的整体稳定性。本文将详细介绍如何在 Spring Boot 中使用 Hystrix 和 Resilience4j 实现降级功能。
367 7
|
8月前
|
Java 开发者 Sentinel
Spring Cloud系列——使用Sentinel进行微服务保护
Spring Cloud系列——使用Sentinel进行微服务保护
86 5