上篇文章:

Spring Cloud系列— Alibaba Sentinel限流https://blog.csdn.net/sniper_fandc/article/details/149944260?fromshare=blogdetail&sharetype=blogdetail&sharerId=149944260&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link

目录

1 熔断策略

1.1 状态机

1.2 慢调用比例(SLOW_REQUEST_RATIO)

1.3 异常比例(ERROR_RATIO)

1.4 异常数(ERROR_COUNT)

2 降级

2.1 捕获异常

2.2 FallbackFactory


1 熔断策略

        当微服务系统中存在某个服务或接口故障,由于调用链路比较复杂,某个接口的故障可能就会导致整个系统不可用。因此需要对故障的接口或服务进行熔断降级,熔断降级主要是对弱依赖服务(不是系统运行的必须服务组件),常见三种策略:

1.1 状态机

        熔断是由断路机(熔断器)统计服务调用的慢调用比例、异常比例和异常数,如果超过阈值则进行熔断,拦截请求该服务的请求;否则放行请求该服务的请求。断路机是基于状态机来完成工作的:

        状态机有三种状态:OPEN、HALF_OPEN和CLOSED。

        CLOSED:所有请求都会通过断路机,通过的过程中统计慢调用比例、异常比例和异常数,如果失败率高于阈值就会转化为OPEN状态。

        OPEN:所有请求都会被断路机拦截,即服务被熔断。每隔一段时间转化为HALF_OPEN状态,并将一定的请求放入断路机。

        HALF_OPEN:OPEN状态每隔一段时间转化为HALF_OPEN状态,并根据放入的请求统计慢调用比例、异常比例和异常数,如果失败率高于阈值,则此时服务还得继续熔断,因此再次转化为OPEN状态;如果失败率低于阈值,则此时服务被视为可以正常访问,不需要进行熔断,因此转化为CLOSED状态。

1.2 慢调用比例(SLOW_REQUEST_RATIO)

        在统计时长内,请求数超过最小请求数,且慢调用(请求响应时间超过最大RT(最大响应时间))比例超过比例阈值,就进行熔断,暂停该资源一定时间(熔断时长)的访问。

        假设order-service服务调用product-service服务的接口,如果product-service服务的接口出现响应速度慢的情况,则会被认为是慢调用请求:

    @RequestMapping("/{productId}")public ProductInfo getProductById(@PathVariable("productId") Integer productId){try {long millis = new Random().nextInt(20)+50;Thread.sleep(millis);//模拟慢调用System.out.println("收到请求,Id:"+productId);return productService.selectProductById(productId);} catch (InterruptedException e) {throw new RuntimeException(e);}}

        将调用方的调用方法定义为资源,便于设置熔断规则:

    @SentinelResource("selectOrderById")public OrderInfo selectOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);//OpenFeign远程调用方式ProductInfo productInfo = productInterface.getProductById(orderInfo.getProductId());orderInfo.setProductInfo(productInfo);return orderInfo;}

        针对资源设置熔断规则,10s内如果请求数超过5次,并且慢调用(响应时间超过50ms)比例超过0.5,则熔断5s:

        当重启服务后,快速手动多次发送请求,如果发送请求超过5次以上,就会出现熔断现象:

1.3 异常比例(ERROR_RATIO)

        在统计时长内,请求数超过最小请求数,且异常比例超过比例阈值,就进行熔断,暂停该资源一定时间(熔断时长)的访问。

        首先在被调用接口中分别设置慢调用和异常两种情况,由于(这里用到了服务降级,会在下面进行阐述)服务降级会针对异常也生效,因此想要观察熔断,就需要先调用慢调用接口(没有设置慢调用的熔断策略,因此不会熔断)会正常通行,再多次调用异常接口触发熔断,最后再调用慢调用接口也会被拦截:

    @RequestMapping("/{productId}")public ProductInfo getProductById(@PathVariable("productId") Integer productId) {if (productId == 1001) {//模拟慢响应try {Thread.sleep(60);} catch (InterruptedException e) {throw new RuntimeException(e);}} else if (productId == 1002) {// 模拟异常throw new RuntimeException("发生异常");}return productService.selectProductById(productId);}

        设置熔断策略为异常比例,10s请求数大于5次,异常比例超过50%就触发5s熔断:

        调用order/1接口,最终会远程调用product/1001接口,不会触发熔断:

        调用order/2接口,最终会远程调用product/1002接口,多次调用会触发熔断(异常比例超过50%):

        在触发熔断后,调用order/1接口,可以发现productInfo为NULL,说明触发熔断,并且服务降级:

1.4 异常数(ERROR_COUNT)

        在统计时长内,请求数超过最小请求数,且发生异常的数量超过设置的异常数,就进行熔断,暂停该资源一定时间(熔断时长)的访问。

        异常数与异常比例类似,只不过熔断判断标准变为超过数字而不是比例。

2 降级

        上述慢调用熔断时,用户会直接看到500内部异常这个响应,这对用户体验并不好。应该针对失败返回用户友好性的提示或默认结果,这就是降级。

        实现服务降级有两种方式:

        1.捕获异常,根据异常逻辑来进行降级。适用于通用场景。

        2.FallbackFactory,适合远程调用场景。

2.1 捕获异常

        由于访问的是/order/{orderId}接口,因此可以在调用时发生异常后返回一个NULL对象:

    @SentinelResource("order-param")@RequestMapping("/{orderId}")public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId) {try {OrderInfo orderInfo = orderService.selectOrderById(orderId);return orderInfo;}catch (UndeclaredThrowableException e){System.out.println("获取订单发生异常,exception:"+e);;return new OrderInfo();}}

        此时在发生熔断,就不会直接在页面显示500内部异常,而是一个NULL对象:

2.2 FallbackFactory

        FallbackFactory是微服务架构中用于服务降级的接口,可以根据远程服务调用失败或异常信息,提供一个降级处理实例,该实例来代替原服务被调用。

        首先需要创建这个降级处理实例,该实例实现FallbackFactory并接受ProductInterface类型的泛型参数:

@Slf4jpublic class ProductFallbackFactory implements FallbackFactory<ProductInterface> {@Overridepublic ProductInterface create(Throwable cause) {return new ProductInterface() {//返回服务降级实例@Overridepublic ProductInfo getProductById(Integer productId) {log.error("查询商品信息异常");return new ProductInfo();}@Overridepublic String param1(Integer productId){return "发生错误";}@Overridepublic String param2(Integer productId,String name){return "发生错误";}@Overridepublic String object(ProductInfo productInfo){return "发生错误";}@Overridepublic String json(ProductInfo productInfo){return "发生错误";}};}}

        ProductInterface类型是OpenFeign远程调用的客户端(抽取),需要注意设置fallbackFactory来和服务降级实例关联:

@FeignClient(value = "product-service",path = "/product", fallbackFactory = ProductFallbackFactory.class)public interface ProductInterface {@RequestMapping("/{productId}")ProductInfo getProductById(@PathVariable("productId") Integer productId);@RequestMapping("/param1")String param1(@RequestParam("productId") Integer productId);@RequestMapping("/param2")String param2(@RequestParam("productId")Integer productId,@RequestParam("name")String name);@RequestMapping("/object")String object(@SpringQueryMap ProductInfo productInfo);@RequestMapping("/json")String json(@RequestBody ProductInfo productInfo);}

        然后还需要定义ProductFallbackFactory的Bean,由于该DefaultFeignConfiguration需要多个远程调用的接口使用,因此不添加五大注解交给Spring来管理,而是由调用方自行扫描注册该Bean:

//创建ProductFallbackFactory的Beanpublic class DefaultFeignConfiguration {@Beanpublic ProductFallbackFactory productFallbackFactory() {return new ProductFallbackFactory();}}

        调用方的启动类上需要配置OpenFeign客户端和FallbackFactory管理的服务降级实例的路径:

@EnableFeignClients(basePackages = {"com.demo.product.api2"},defaultConfiguration = DefaultFeignConfiguration.class)

        最后在配置文件中开启OpenFeign的Sentinel的功能:

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

        重启服务,观察服务降级:

        可以发现,开启OpenFeign的Sentinel功能后,远程调用的接口也出现在簇点链路中,针对远程调用设置熔断降级:

        此时在多次慢调用出发熔断后,不再是直接的500内部异常,而是远程调用的服务降级。并且该服务降级返回了NULL的productInfo对象(服务降级实例),并不是像异常处理那样处理粒度很粗。

        注意:FallbackFactory不仅对熔断生效对限流也生效,即如果触发限流,页面不再显示Blocked by Sentinel,而是返回服务降级实例。并且,服务降级还会对异常生效,即只要程序发生异常,就会走服务降级。因此发生服务降级现象,不一定是因为熔断,也可能是因为限流或异常。

下篇文章:

Spring Cloud系列—Alibaba Sentinel授权与规则管理及推送https://blog.csdn.net/sniper_fandc/article/details/149945898?fromshare=blogdetail&sharetype=blogdetail&sharerId=149945898&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link

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

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

相关文章

Spring Boot 使用 @NotBlank + @Validated 优雅校验参数

在日常开发中&#xff0c;我们常用 if (isBlank(...)) 来判断参数是否为空&#xff0c;但这种方式不仅繁琐&#xff0c;而且容易遗漏。 Spring 生态中推荐使用 JSR-303 校验注解&#xff08;NotBlank、NotNull 等&#xff09;配合 Validated 实现自动校验&#xff0c;大幅减少手…

网络安全(Java语言)简单脚本汇总 (一)

文章目录敏感信息探测脚本源代码思路URL批量存活探测器源代码思路端口扫描器源代码思路 敏感信息探测脚本 源代码/*** description 该脚本通过分析HTTP响应头&#xff0c;来检测可能暴露服务器信息的安全隐患*/import java.io.IOException; import java.net.HttpURLConnection;…

buuctf_NSBlogin_http_upload(极客2019+ACTF2020新生赛)

今天做三1个web 题目&#xff1a;NSB_login用户名有admin&#xff0c;看源码&#xff1a;I like rockyou&#xff01;今天学习到&#xff0c;kali里面有密码爆破的文件叫rockyou.txt&#xff08;/usr/share/wordlists/&#xff09;&#xff08;没kali也可以去https://gitcode.c…

IDEA如何引用brew安装的openjdk

因为 brew 安装的 openjdk@21 目录结构和 IDEA 期望的 JDK 目录不一样。所以默认brew安装的jdk,在IDEA中是无法识别到的。 一、创建软连接 sudo mkdir -p /Library/Java/JavaVirtualMachines sudo ln -sfn /usr/local/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/Java…

【Unity3D】Spine黑线(预乘问题)、贴图边缘裁剪问题

一、黑线问题 Spine正确的导出和Unity导入设置&#xff08;解决黑边/彩条带问题&#xff09;_spine导出的图片有黑边-CSDN博客 采用&#xff08;已解决问题&#xff09; Texture 打包器启用 Premultiply alpha ,禁用Bleed Unity Texture 设置中禁用 sRGB (Color Texture) 和…

嵌入式系统学习Day18(文件编程-系统调用文件IO)

- open#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 功能:打开文件 参数:pathname --- 文件名 flags 必选:O_RDONLYO_WRONLY…

Vue浅学

概述在最近的学习任务中了解了 Vue&#xff0c;并对其产生了浓厚的兴趣&#xff0c;现在分享一下我的学习所得关键字其一statestate 是 Vuex 存储中的“状态对象”&#xff0c;用于存储整个应用的共享数据&#xff08;如用户信息、令牌、权限等&#xff09;&#xff0c;比如&am…

机器翻译:Hugging Face库详解

文章目录一、Hugging Face概述1.1 Hugging Face介绍1.2 核心理念&#xff1a;模型即服务&#xff0c;但以开源形式二、核心架构2.1 Transformers库&#xff1a;模型交互的统一接口2.2 Datasets库&#xff1a;高效的数据处理引擎2.3 Tokenizers库&#xff1a;文本与模型的“翻译…

服务器安装gielab社区版

第一步&#xff1a;安装Gitlab 1,使用的是CentOs镜像(服务器最低配置为4核8g内存才行要不然带不动) 登录目标实例。 2,执行如下命令&#xff0c;安装所需依赖。 1 sudo yum install -y curl policycoreutils-python openssh-server 3,执行如下命令&#xff0c;启动SSH服务…

C#报错:System.NullReferenceException:“未将对象引用设置到对象的实例。”

C#使用自定义的类创建数组时&#xff0c;使用时报错&#xff0c;报错内容如下图&#xff1a;原因&#xff1a;C#中的数组是引用类型。当声明自定义类数组时&#xff0c;数组本身会被创建&#xff0c;但其元素&#xff08;即自定义类的实例&#xff09;默认未被实例化&#xff0…

Maven 的 module 管理

一、Maven 的 module 管理 1. 什么是 Maven module&#xff1f; Maven module&#xff08;模块&#xff09;&#xff0c;是 Maven 多模块项目结构&#xff08;multi-module project&#xff09;中的核心概念。它允许你将一个大型项目拆分为若干独立的小项目&#xff08;模块&am…

现在都是APP,小程序抢购,支持浏览器不支持 SSE

在 APP 和小程序抢购场景中&#xff0c;通常不原生支持SSE&#xff08;Server-Sent Events&#xff09;&#xff0c;这与浏览器对 SSE 的支持情况不同&#xff0c;具体如下&#xff1a;APP&#xff1a;一般情况下&#xff0c;APP 端不支持原生 SSE。若使用 UniApp 开发&#xf…

Spring Boot 深度解析:从原理到实践

一、Spring Boot 本质与核心价值 1.1 什么是 Spring Boot&#xff1f; Spring Boot 是 Spring 生态的革命性框架&#xff0c;旨在解决传统 Spring 开发的复杂性。它通过"约定优于配置"&#xff08;Convention Over Configuration&#xff09;理念&#xff0c;提供开箱…

WebSocket-java篇

问题引入消息推送的方式我们要实现&#xff0c;服务器把消息推送到客户端&#xff0c;可以轮训&#xff0c;长轮训还有sseWebSocket理论WebSocket 的由来与核心价值诞生背景&#xff1a;解决 HTTP 协议在实时通信中的固有缺陷&#xff08;单向请求-响应模式&#xff09;核心驱动…

用Python从零开始实现神经网络

反向传播算法用于经典的前馈人工神经网络。 它仍然是训练大型深度学习网络的技术。 在这个教程中&#xff0c;你将学习如何用Python从头开始实现神经网络的反向传播算法。 完成本教程后&#xff0c;您将了解&#xff1a; 如何将输入前向传播以计算输出。如何反向传播错误和…

算法148. 排序链表

题目&#xff1a;给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。示例 1&#xff1a;输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4] 示例 2&#xff1a;输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5] 示例 3&a…

在腾讯云CodeBuddy上实现一个AI聊天助手

在腾讯云CodeBuddy上实现一个AI聊天助手项目 在当今数字化时代&#xff0c;AI聊天助手已经成为一种非常流行的应用&#xff0c;广泛应用于客户服务、智能助手等领域。今天&#xff0c;我们将通过腾讯云CodeBuddy平台&#xff0c;实现一个基于Spring Boot和OpenAI API的AI聊天助…

JavaScript Array.prototype.flatMap ():数组 “扁平化 + 映射” 的高效组合拳

在 JavaScript 数组处理中&#xff0c;我们经常需要先对每个元素进行转换&#xff08;映射&#xff09;&#xff0c;再将结果 “铺平”&#xff08;扁平化&#xff09;。比如将数组中的每个字符串按空格拆分&#xff0c;然后合并成一个新数组。传统做法是先用map()转换&#xf…

区块链与元宇宙:数字资产的守护者

1 区块链支撑元宇宙数字资产的底层逻辑1.1 不可篡改性构建信任基石区块链的不可篡改性为元宇宙数字资产提供了坚实的信任基础。其核心在于分布式账本技术&#xff0c;当一笔数字资产交易发生时&#xff0c;会被打包成区块并广播至网络中的所有节点。每个节点都会对这笔交易进行…

Linux软件编程:进程和线程(进程)

进程一、基本概念进程&#xff1a;是程序动态执行过程&#xff0c;包括创建、调度、消亡程序&#xff1a;存放在外存的一段数据的集合二、进程创建&#xff08;一&#xff09;进程空间分布每个进程运行起来后&#xff0c;操作系统开辟0-4G的虚拟空间进程空间&#xff1a;用户空…