Sentinel的隔离和降级

文章目录

  • 1、概念简介
  • 2、FeignClient整合Sentinel
    • 2.1、修改配置,开启sentinel功能
    • 2.2、编写失败降级逻辑
    • 2.3、总结
  • 3、线程隔离(舱壁模式)
    • 3.1、线程隔离的实现方式
    • 3.2、sentinel的线程隔离
      • 1)配置隔离规则
      • 2)Jmeter测试
    • 3.3、总结
  • 4、熔断降级
    • 4.1、慢调用
      • 1)设置慢调用
      • 2)设置熔断规则
      • 3)测试
    • 4.2、异常比例、异常数
      • 1)设置异常请求
      • 2)设置熔断规则
      • 3)测试

🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。
🦅主页:@逐梦苍穹
📕所属专栏:微服务
✈ 您的一键三连,是我创作的最大动力🌹

1、概念简介

限流是一种预防措施,虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。
而要将这些故障控制在一定范围,避免雪崩,就要靠**线程隔离(舱壁模式)和熔断降级手段了。
线程隔离之前讲到过:调用者在调用服务提供者时,给每个调用的请求分配独立线程池,出现故障时,最多消耗这个线程池内资源,避免把调用者的所有资源耗尽。

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

可以看到,不管是线程隔离还是熔断降级,都是对
客户端**(调用方)的保护。需要在调用方 发起远程调用时做线程隔离、或者服务熔断。
而我们的微服务远程调用都是基于Feign来完成的,因此我们需要将Feign与Sentinel整合,在Feign里面实现线程隔离和服务熔断。

2、FeignClient整合Sentinel

SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合Feign和Sentinel。

2.1、修改配置,开启sentinel功能

修改OrderService的application.yml文件,开启Feign的Sentinel功能:

feign:sentinel:enabled: true # 开启feign对sentinel的支持

2.2、编写失败降级逻辑

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

①方式一:FallbackClass,无法对远程调用的异常做处理
②方式二:FallbackFactory,可以对远程调用的异常做处理,我们选择这种

这里演示方式二的失败降级处理
步骤一:在feing-api项目中定义类,实现FallbackFactory:
image.png
代码:

package cn.xzl.feign.clients.fallback;import cn.xzl.feign.clients.UserClient;
import cn.xzl.feign.pojo.User;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;/*** @author 逐梦苍穹* @date 2024/4/24 11:35*/@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {@Overridepublic UserClient create(Throwable throwable) {return new UserClient() {@Overridepublic User findById(Long id) {log.error("查询用户异常", throwable);return new User();}};}
}

步骤二:在feing-api项目中的DefaultFeignConfiguration类中将UserClientFallbackFactory注册为一个Bean:

@Bean
public UserClientFallbackFactory userClientFallbackFactory(){return new UserClientFallbackFactory();
}

步骤三:在feing-api项目中的UserClient接口中使用UserClientFallbackFactory:

import cn.xzl.feign.clients.fallback.UserClientFallbackFactory;
import cn.xzl.feign.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}

查看注解源码,翻译过来如下:
image.png
重启后,访问一次订单查询业务,然后查看sentinel控制台,可以看到新的簇点链路:
image.png

2.3、总结

Sentinel支持的雪崩解决方案:

线程隔离(仓壁模式)
降级熔断

Feign整合Sentinel的步骤:

在application.yml中配置:feign.sentienl.enable=true
给FeignClient编写FallbackFactory并注册为Bean
将FallbackFactory配置到FeignClient

3、线程隔离(舱壁模式)

3.1、线程隔离的实现方式

线程隔离有两种方式实现:

  • 线程池隔离
  • 信号量隔离(Sentinel默认采用

如图:

线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果
信号量隔离:不创建线程池,而是计数器模式,记录业务使用的线程数量,达到信号量上限时,禁止新的请求。

两者的优缺点:

|
| 信号量隔离 | 线程池隔离 |
| — | — | — |
| 优点 | 轻量级,无额外开销 | 支持主动超时;
支持异步调用 |
| 缺点 | 不支持主动超时;
不支持异步调用 | 线程的额外开销较大 |
| 适用场景 | 高频调用、高扇出 | 低扇出 |

这里再解释两个概念,即何为"低扇出"和"高扇出":
高扇出和低扇出是软件架构中常用的两个概念,用来描述系统中组件之间的连接数量和复杂度。

  1. 高扇出(High Fan-Out)

定义:高扇出指的是一个组件向多个其他组件发送消息、调用服务或传递数据的情况。换句话说,一个组件与多个其他组件进行交互。
特点:高扇出的系统通常具有许多连接、依赖和交互,信息流动频繁,组件之间的耦合度较高。
优点:能够实现信息的广泛传播和共享,提高系统的灵活性和可扩展性,允许系统中的组件彼此之间进行相对独立的工作。
缺点:可能导致系统的复杂性增加、维护困难、调试复杂,增加了系统的耦合度和风险,同时也会增加系统中的通信开销和延迟。

  1. 低扇出(Low Fan-Out)

定义:低扇出指的是一个组件与少数其他组件之间的连接数量较少的情况。换句话说,一个组件与少数其他组件进行交互。
特点:低扇出的系统通常具有简单的连接关系,组件之间的耦合度较低,信息流动相对较少。
优点:能够降低系统的复杂性,提高系统的可维护性和可测试性,降低系统中的耦合度和风险,减少系统中的通信开销和延迟。
缺点:可能导致信息流动不畅、信息共享不足,系统的灵活性和可扩展性受到一定程度的限制,某些功能可能无法实现。

在实际的软件设计和架构中,通常需要根据系统的需求、性能要求、可维护性等因素来权衡选择高扇出还是低扇出。
一般来说,应该尽量避免过度的高扇出或低扇出,而是根据实际情况进行合理的设计和优化,以实现系统的高效运行和良好的性能。

3.2、sentinel的线程隔离

用法说明
在添加限流规则时,可以选择两种阈值类型:

  • QPS:就是每秒的请求数,在快速入门中已经演示过
  • 线程数:是该资源能使用用的tomcat线程数的最大值。也就是通过限制线程数量,实现线程隔离(舱壁模式)。

案例需求:给 order-service服务中的UserClient的查询用户接口设置流控规则,线程数不能超过 2。然后利用jemeter测试。

1)配置隔离规则

选择feign接口后面的流控按钮:

填写表单:

image.png

2)Jmeter测试

选择《阈值类型-线程数<2》:

一次发生10个请求,有较大概率并发线程数超过2,而超出的请求会走之前定义的失败降级逻辑。
查看运行结果:

发现虽然结果都是通过了,不过部分请求得到的响应是降级返回的null信息。

3.3、总结

线程隔离的两种手段:

信号量隔离
线程池隔离

信号量隔离的特点:

基于计数器模式,简单,开销小

线程池隔离的特点:

基于线程池模式,有额外开销,但隔离控制更强

4、熔断降级

熔断降级是解决雪崩问题的重要手段。
其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。
即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。
断路器控制熔断和放行是通过状态机来完成的:

状态机包括三个状态:

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

断路器熔断策略有三种:慢调用、异常比例、异常数

4.1、慢调用

慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。
在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。
例如:

解读:RT超过500ms的调用是慢调用,统计最近10000ms内的请求,如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。
案例
需求:给 UserClient的查询用户接口设置降级规则,慢调用的RT阈值为50ms,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5

1)设置慢调用

修改user-service中的/user/{id}这个接口的业务。通过休眠模拟一个延迟时间:
image.png
此时,orderId=101的订单,关联的是id为1的用户,调用时长为60ms:
image.png
orderId=102的订单,关联的是id为2的用户,调用时长为非常短:
image.png

2)设置熔断规则

下面,给feign接口设置降级规则:

规则:
image.png
超过50ms的请求都会被认为是慢请求

3)测试

在浏览器访问:http://localhost:8088/order/101,快速刷新5次,可以发现:
image.png
触发了熔断,请求时长缩短至26ms,快速失败了,并且走降级逻辑,返回的null
在浏览器访问:http://localhost:8088/order/102,竟然也被熔断了。

4.2、异常比例、异常数

异常比例或异常数:统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值(或超过指定异常数),则触发熔断。
例如,一个异常比例设置:

解读:统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于0.4,则触发熔断。
一个异常数设置:

解读:统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于2次,则触发熔断。
案例
需求:给 UserClient的查询用户接口设置降级规则,统计时间为1秒,最小请求数量为5,失败阈值比例为0.4,熔断时长为5s

1)设置异常请求

首先,修改user-service中的/user/{id}这个接口的业务。手动抛出异常,以触发异常比例的熔断:

也就是说,id 为 2时,就会触发异常

2)设置熔断规则

下面,给feign接口设置降级规则:

规则:

在5次请求中,只要异常比例超过0.4,也就是有2次以上的异常,就会触发熔断。

3)测试

在浏览器快速访问:http://localhost:8088/order/102,快速刷新5次,触发熔断。
此时,我们去访问本来应该正常的103也被熔断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/838972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

南加州大学字节提出MagicPose,提供逼真的人类视频生成,实现生动的运动和面部表情传输,以及不需要任何微调的一致的野外零镜头生成。

MagicPose可以精确地生成外观一致的结果&#xff0c;而原始的文本到图像模型(如Stable Diffusion和ControlNet)很难准确地保持主体身份信息。 此外&#xff0c;MagicPose模块可以被视为原始文本到图像模型的扩展/插件&#xff0c;而无需修改其预训练的权重。 相关链接 论文链…

k8s pv 一直是release状态

如下图所示&#xff0c;pv 一直是release状态 这个时候大家可能就会想到现在我的 PVC 被删除了&#xff0c;PV 也变成了 Released 状态&#xff0c;那么我重建之前的 PVC 他们不就可以重新绑定了&#xff0c;事实并不会&#xff0c;PVC 只能和 Available 状态的 PV 进行绑定。…

Vue 对象

在 Vue.js 中&#xff0c;操作对象是常见的任务之一。Vue 提供了许多方法和指令来方便地操作对象&#xff0c;包括动态添加属性、遍历对象、响应式更新等。以下是一些常见的对象操作及其详细说明和示例。 创建对象 在 Vue 组件的 data 中创建对象&#xff1a; export defaul…

children和childrenNodes及nodeValue

在JavaScript中&#xff0c;尤其是当处理DOM元素时&#xff0c;children[0] 和 childNodes[0] 确实存在区别&#xff0c;尽管它们看起来都像是访问某个元素子节点的方式。以下是它们之间的主要区别&#xff1a; children 属性 children 属性是一个只读的HTMLCollection&#…

SQL 面试系列(一)【留存率问题】

前言 在学 HQL 之前是不太了解 SQL 的&#xff0c;以为 SQL 只可以实现 CRUD &#xff0c;直到面试的公司让我下去多了解一些 SQL &#xff0c;我才最近开始再次深入学习 MySQL 和 Oracle。而且越学越发现 SQL 真的是一门很有深度的语言&#xff0c;我以前的使用只是皮毛而已&a…

如何远程连接默认端口?

远程连接是指通过网络实现两个或多个计算机之间的连接和通信。在进行远程连接时&#xff0c;使用的端口号是一个重要的参数。端口号是计算机上正在运行的特定应用程序的标识符。每个应用程序都会监听一个或多个特定的端口号&#xff0c;以便接收来自其他计算机的连接请求&#…

Android正向开发实现客户端证书认证

前言 如果第三方模块被混淆,那hook方式均不能生效。这时就需要根据系统包去定位校验的函数,因此需要对安卓开发者是如何实现客户端证书校验的有一定了解,接下来就介绍这部分内容。 开发者实现客户端证书校验的本质是:证书/密钥 + 代码。 在形式上有:证书校验、公钥校验和…

【内存泄漏Bug】registerReceiver Are you missing a call to unregisterReceiver()异常分析及解决

问题描述 开发一款WIFI管理APP&#xff0c;再wifi列表页面注册了广播监听&#xff0c;监听网络变化&#xff0c;页面是常驻内存的&#xff0c;跳转到其他app或者其他页面的时候&#xff0c;此页面存在被系统销毁的可能。 android.app.IntentReceiverLeaked: Activity com.xx.a…

Object类,你学会了吗?

在 Java 编程中,Object 类是所有类的根类,了解 Object 类的原理和功能对于成为一名优秀的 Java 程序员至关重要。 本文将深入介绍 Object 类,帮助准备面试的程序员更好地理解这个关键的 Java 类。 什么是 Object 类? Object 类位于 java.lang 包中,是 Java 中的基本类之…

Leetcode 112:路径总和

给定一个二叉树和一个目标和&#xff0c;判断该树中是否存在根节点到叶子节点的路径&#xff0c;这条路径上所有节点值相加等于目标和。 说明: 叶子节点是指没有子节点的节点。 思路&#xff1a;遍历存储每条路径。当前节点为叶子节点时&#xff0c;求和。并判断是否等于目标…

【Linux】:进程优先级

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux进程优先级的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到…

LSTM实例解析

大家好&#xff0c;这里是七七&#xff0c;今天带给大家的实例解析。以前也用过几次LSTM模型&#xff0c;但由于原理不是很清楚&#xff0c;因此不能清晰地表达出来&#xff0c;这次用LSTM的时候&#xff0c;去自习研究了原理以及代码&#xff0c;来分享给大家此次经历。 一、简…

网络设置 —— Http 响应头和请求头的设置

get请求可以使用GetAsync方法 Post请求 使用PostAsync&#xff0c; delete请求 使用DeleteAsync Put请求 使用PutAsync 请求的完整写法 HttpResponseMessage res await new HttpClient().SendAsync(reg); string data awai…

JAVA 中 HTTP 基本认证(Basic Authentication)

目录 服务端这么做服务端告知客户端使用 Basic Authentication 方式进行认证服务端接收并处理客户端按照 Basic Authentication 方式发送的数据 客户端这么做如果客户端是浏览器如果客户端是 RestTemplat如果客户端是 HttpClient 其它参考 服务端这么做 服务端告知客户端使用 …

AWS CloudWatch日志组中关于中文关键字的查询

问题 在AWS CloudWatch日志组中&#xff0c;想要查询出包含中文关键字的错误日志&#xff0c;结果&#xff0c;AWS说语法错误。 最开始&#xff0c;使用如下查询&#xff0c;查询可能的错误日志&#xff1a; 查询语句&#xff0c;如下&#xff1a; {($.log %ERROR%) }具体效…

CSS预处理器Sass详解

CSS预处理器Sass 1. 变量&#xff08;Variables&#xff09;&#xff1a; 变量在Sass中以$开头&#xff0c;用于存储值&#xff0c;以便在多个地方重用。 $primary-color: #007BFF;body {color: $primary-color;}2. 嵌套规则&#xff08;Nested Rules&#xff09;&#xff1a…

C语言中字符串相关的函数解析

C语言中没有string类型&#xff0c;字符串通常放在常量字符串或字符数组中&#xff0c;下面来介绍一些常用的字符串相关的操作函数。 strlen strlen用来求一个字符串的长度&#xff0c;其函数原型如下&#xff1a; size_t strlen ( const char * str ); 使用strlen需要注意以…

ACL的几种类型

ACL&#xff08;Access Control List&#xff0c;访问控制列表&#xff09;主要有以下几种类型&#xff1a; 数字型ACL&#xff1a;这是传统的ACL标识方法&#xff0c;创建ACL时指定一个唯一的数字来标识该ACL。命名型ACL&#xff1a;通过名称代替编号来标识ACL&#xff0c;用…

实战Java虚拟机-高级篇

一、GraalVM 什么是GraalVM GraalVM是Oracle官方推出的一款高性能JDK&#xff0c;使用它享受比OpenJDK或者OracleJDK更好的性能。GraalVM的官方网址&#xff1a;https://www.graalvm.org/官方标语&#xff1a;Build faster, smaller, leaner applications。 更低的CPU、内存…

js实现鼠标拖拽多选功能

实现功能 在PC端的H5页面中&#xff0c;客户拖动鼠标可以连选多个选项 效果展示 具体代码如下 <!DOCTYPE html> <html><head><title>鼠标拖拽多选功能</title><script src"https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js&quo…