当前位置: 首页 > news >正文

微服务保护学习笔记(四)FeignClient整合Sentinel、线程隔离(舱壁模式)、熔断降级

文章目录

  • 前言
  • 3 隔离和降级
    • 3.1 FeignClient整合Sentinel
      • 3.1.1 搭建SpringCloud项目
      • 3.1.2 修改配置文件
      • 3.1.3 编写失败降级逻辑
    • 3.2 线程隔离(舱壁模式)
      • 3.2.1 线程隔离的实现方式
      • 3.2.2 线程池隔离
    • 3.3 熔断降级
      • 3.3.1 熔断降级的实现方式
      • 3.3.2 慢调用比例
      • 3.3.3 异常比例、异常数

前言

微服务保护学习笔记(一)雪崩问题及解决方案、Sentinel介绍与安装
微服务保护学习笔记(二)簇点链路、流控操作、流控模式(关联、链路)
微服务保护学习笔记(三)流控效果(warm up、排队等待)、热点参数限流

3 隔离和降级

限流是一种预防措施,它可以尽量避免因高并发而引起的服务故障。但服务还会因为其它原因而故障,而要将这些故障控制在一定范围内避免雪崩,就要依靠线程隔离(舱壁模式)和熔断降级手段了。

  • 线程隔离:服务调用者在调用服务提供者时,给每个调用请求分配独立线程池,出现故障时,这个请求最多消耗这个线程池内的资源,避免把调用者的所有资源耗尽。

  • 熔断降级:在调用方这边加入断路器,统计对服务提供者的调用,如果调用的失败比例过高,则熔断该业务,不允许访问该服务提供者。

可以看到,不管是线程隔离还是熔断降级,都是对客户端(调用方)的保护,需要在调用方发起远程调用时做线程隔离或者服务熔断。

SpringCloud微服务远程调用都是基于Feign来完成的,因此需要将Feign与Sentinel整合,在Feign里面实现线程隔离和服务熔断。

3.1 FeignClient整合Sentinel

3.1.1 搭建SpringCloud项目

创建一个SpringCloud项目,sd-user-servicesd-order-service微服务均注册到Eureka中:

sd-user-service微服务中有一个/user/query接口,调用该接口后会通过Feign调用sd-order-service微服务:

// com.hsgx.user.controller.UserController@Autowired
private OrderClient orderClient;@GetMapping("/query")
public String query(String id) {String order = orderClient.queryById(id);return "查询用户" + id + "成功," + order;
}
// com.hsgx.order.controller.OrderController@GetMapping("/query")
public String query(String id) {return "查询订单" + id + "成功";
}

3.1.2 修改配置文件

修改sd-user-service微服务(调用方)的配置文件,开启Feign的Sentinel功能:

feign:sentinel:enabled: true

3.1.3 编写失败降级逻辑

业务失败后,不能直接报错,而应该返回一个友好提示或者默认结果,这就是失败降级逻辑。

  • 1)在sd-user-service微服务中定义类,实现FallbackFactory
// com.hsgx.user.config.OrderClientFallbackFactorypublic class OrderClientFallbackFactory implements FallbackFactory<OrderClient> {@Overridepublic OrderClient create(Throwable throwable) {return new OrderClient() {@Overridepublic String queryById(String id) {return "调用order微服务失败";}};}
}
  • 2)在DefaultFeignConfiguration类中将OrderClientFallbackFactory注册为一个Bean
// com.hsgx.user.config.DefaultFeignConfiguration@Bean
public OrderClientFallbackFactory orderClientFallbackFactory(){return new OrderClientFallbackFactory();
}
  • 3)在OrderClient接口中使用OrderClientFallbackFactory
// com.hsgx.user.feign.OrderClient@FeignClient(value = "sd-order-service",configuration = DefaultFeignConfiguration.class,fallback = OrderClientFallbackFactory.class)
public interface OrderClient {@GetMapping("/order/query")String queryById(@RequestParam("id") String id);
}

重启sd-user-service微服务后,再次访问/user/query接口,然后查看Sentinel控制台,可以看到新的簇点链路:

3.2 线程隔离(舱壁模式)

3.2.1 线程隔离的实现方式

如上图所示,线程隔离有两种方式实现:

  • 线程池隔离:给每个调用业务分配一个线程池,利用线程池本身实现隔离效果。例如,给访问服务A的线程分配一个单独的线程池,如果访问服务A失败,则只在当前线程池中失败,而不会影响其他线程池。
  • 信号量隔离(即QPS):不创建线程池,而是计数器模式,记录调用业务使用的线程数量,达到信号量上限时,禁止新的请求。

3.2.2 线程池隔离

在给资源添加限流规则时,阈值类型可以选择“QPS”或者“线程数”。而选择“线程数”时,就是该资源能使用的线程数最大值,从而实现线程隔离。

下面对线程池隔离进行测试:

  • 1)配置隔离规则,使GET:http://sd-order-service/order/query资源的最大线程数为2

  • 2)使用jmeter进行测试,使线程数为10

  • 3)测试/user/query?id=1

测试结果发现,虽然结果都是通过,不过部分请求得到的响应是降级后的。测试结果符合预期。

3.3 熔断降级

3.3.1 熔断降级的实现方式

熔断降级思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该调用服务,即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。

断路器控制熔断和放行是通过状态机来完成的:

如上图所示,状态机包括三个状态:

  • closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则会切换到open状态。
  • open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。open状态5秒后会进入half-open状态。
  • half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。如果请求成功,则切换到closed状态;如果请求失败,则切换到open状态。

在Sentinel控制台新增降级规则时,有三种熔断策略可选:

3.3.2 慢调用比例

响应时长(RT)大于指定时长的调用请求则被认定为慢调用请求。该策略的原理如下:

在以上配置中,RT超过500ms的请求则是慢调用请求。统计最近10000ms内的调用请求,如果请求量超过10次,且慢调用比例超过0.5(即超过5次),则触发熔断,熔断时长为5秒。然后状态机进入half-open状态,放行一次请求做测试。

下面对慢调用策略进行测试:

  • 1)修改sd-order-service微服务的/order/query接口,通过休眠模拟一个延迟时间:
@RestController
@RequestMapping("/order")
public class OrderController {@GetMapping("/query")public String query(String id) throws InterruptedException {if("1".equals(id)) {// 当id=1时,触发慢调用Thread.sleep(600);}return "查询订单" + id + "成功";}}

此时调用/order/query?id=1接口的响应时间较长,超过500ms,将被认定为慢调用请求:

而调用/order/query?id=2接口的响应时间很短,不超过500ms,将不会被认定为慢调用请求:

  • 2)设置熔断规则

  • 3)使用jmeter进行测试,设置20秒内发送50个请求

  • 4)调用/user/query?id=1接口

  • 5)调用/user/query?id=2接口

3.3.3 异常比例、异常数

异常比例和异常数策略的原理是一样的,只是前者以比例来限定阈值,后置以具体的数值来限定阈值,例如:

在以上配置中,统计最近1000ms内的调用请求,如果请求量超过10次,且异常比例超过0.4(异常数超过4次),则触发熔断,熔断时长为5秒。

下面对异常比例策略进行测试:

  • 1)修改sd-order-service微服务的/order/query接口,手动抛出异常,模拟出现异常:
@GetMapping("/query")
public String query(String id) throws InterruptedException {if("1".equals(id)) {// 当id=1时,触发慢调用Thread.sleep(600);}if("2".equals(id)) {// 当id=2时,触发异常throw new RuntimeException("查询订单异常");}return "查询订单" + id + "成功";
}
  • 2)调用/user/query?id=3接口,此时是正常访问的

  • 3)设置上述熔断规则,并使用jmeter进行测试,设置1秒内发送20个请求调用/user/query?id=2接口,触发熔断

  • 4)在5s内再次调用/user/query?id=3接口,会发现已被阻止,即熔断已发生。5s后再次调用,发现服务恢复正常。

本节完,更多内容请查阅分类专栏:微服务学习笔记

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析
  • MyBatis3源码深度解析
  • Redis从入门到精通
  • MyBatisPlus详解
  • SpringCloud学习笔记

http://www.mrgr.cn/news/25158.html

相关文章:

  • 大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
  • 亲测好用,ChatGPT 3.5/4.0新手使用手册~
  • UEFI学习笔记(四):inf、dec和dsc
  • tekton pipeline resources
  • 项目启动 | 盘古信息携手晶捷电子,开启数字化生产管理新纪元
  • GDB的基本使用方法(之一)
  • linux驱动之模块化编程
  • 【数据结构】线性表的定义和基本操作
  • Tita的OKR:公司级 OKR 案例
  • 基于R语言结构方程模型分析与实践技术应用
  • Servlet(三)
  • 将独立的生成式AI系统整合为一个大脑
  • 从Apple Intelligence到IoT Intelligence,端侧生成式AI时代加速到来
  • python绘制3D瀑布图
  • 进程调度相关
  • windows.open使用
  • 低空经济 | 世界经济论坛:先进空中交通白皮书
  • JavaScript在网页设计中的应用案例
  • 图像拼接C++代码记录
  • Sqlserver常用sql