手写Hystrix基本原理

本文已收录于专栏
《中间件合集》

目录

  • 概念说明
    • 什么是Hystrix
    • Hystrix解决的问题
  • 提供服务
  • 工作流程
  • 代码实现
    • HystrixSDK
      • MyHystrixCommand注解
      • MyHystrixProperty注解
      • MyAspect注解解释器
    • 发送请求端
      • 引入Hystrix的依赖
      • 调用代码
    • 接收请求端
    • 执行效果
      • 发送请求端
  • 总结提升

概念说明

什么是Hystrix

  Spring Cloud Hystrix 是基于 Netflix 公司的开源组件 Hystrix 实现的,它提供了熔断器功能,能够有效地阻止分布式微服务系统中出现联动故障,以提高微服务系统的弹性。Spring Cloud Hystrix 具有服务降级、服务熔断、线程隔离、请求缓存、请求合并以及实时故障监控等强大功能。

Hystrix解决的问题

在这里插入图片描述
  所有服务都需要请求服务T,当B服务有大量的请求,导致服务T所属的服务器CPU太高,无法立即处理请求,导致服务瘫痪。瘫痪之后就会导致所有的请求推挤在服务U然后一直向上堆积。这时候当服务A去访问服务T或者服务U的时候也请求不同。导致整个体统都瘫痪了。我们把这个情况成为灾难性的雪崩效应。Hystrix 就能很好的解决这一问题。

提供服务

Spring Cloud Hystrix提供了一系列强大的功能来处理分布式系统中的延迟和容错问题。下面是对这些功能的详细说明:

  1. 「 服务降级(Fallback)」:当一个服务发生故障或超时时,Hystrix可以提供一个备用的响应或执行一些预定义的逻辑,从而避免对整个系统的影响。通过定义降级逻辑,例如返回默认值、执行备用方法或从缓存中获取数据,可以保证系统的可用性。
  2. 「 服务熔断(Circuit Breaker)」:Hystrix可以根据一定的条件自动开启或关闭服务的熔断。当服务调用失败率达到一定阈值时,Hystrix会自动开启熔断,之后的请求将直接返回降级的响应,避免对后端服务的继续调用,从而保护后端服务免受进一步的压力。一段时间后,Hystrix会尝试恢复对服务的调用,如果调用成功,则关闭熔断,否则继续开启熔断。
  3. 「 线程隔离(Thread Isolation)」:Hystrix通过使用线程池隔离不同的服务调用,可以防止一个服务的故障导致整个系统的故障。每个服务都运行在独立的线程池中,从而提供了更好的资源隔离和保护。这样可以避免由于一个服务的延迟或故障导致其他服务的阻塞。
  4. 「 请求缓存(Request Caching)」:Hystrix可以缓存相同的请求结果,以避免重复的调用。当多个请求需要调用同一个服务时,Hystrix会先从缓存中查找结果,如果存在则直接返回,而不需要再次调用服务。这样可以减少对后端服务的请求次数,提高系统的性能和吞吐量。
  5. 「请求合并(Request Collapsing) 」:Hystrix可以将多个相同类型的请求合并为一个批量请求,从而减少网络开销和提高系统的性能。当多个请求需要调用同一个服务时,Hystrix会将这些请求合并为一个批量请求,并一次性发送给后端服务,然后将结果拆分返回给各个请求。这样可以减少网络通信的次数,提高系统的效率。
  6. 「 实时故障监控(Real-time Monitoring)」:Hystrix提供了实时监控和指标收集功能,可以通过Hystrix Dashboard或Turbine来查看服务的健康状况、请求的响应时间、错误率等指标。这样可以帮助开发人员快速发现和解决问题,保证系统的稳定性和可靠性。

  通过使用Spring Cloud Hystrix,我们可以更好地处理分布式系统中的故障和延迟问题,提高系统的可靠性和容错性。

工作流程

  当在5秒内A服务向B服务发送了10个请求,并且满足错误率达到50%。那么断路器开启,进行熔断机制,在30秒内不在请求B服务,直接请求我们定义的托底方法。这些参数例如5s、10个请求、错误率都是可以在代码中进行配置的。根据不同的需求填写不同的参数。
在这里插入图片描述

代码实现

HystrixSDK

sdk是每个请求的发送端需要引入的服务,使用sdk中的一些注解来完成具体的服务

MyHystrixCommand注解

package com.example.hystrixdemo.utils;import com.netflix.hystrix.contrib.javanica.annotation.HystrixException;
import com.netflix.hystrix.contrib.javanica.annotation.ObservableExecutionMode;import java.lang.annotation.*;@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited  //表示注解可以被子类继承
public @interface MyHystrixCommand {String groupKey() default "";String commandKey() default "";String threadPoolKey() default "";String fallbackMethod() default "";MyHystrixProperty[] commandProperties() default {};MyHystrixProperty[] threadPoolProperties() default {};Class<? extends Throwable>[] ignoreExceptions() default {};ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;HystrixException[] raiseHystrixExceptions() default {};String defaultFallback() default "";}

MyHystrixProperty注解

package com.example.hystrixdemo.utils;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyHystrixProperty {String name();String value();
}

MyAspect注解解释器

package com.example.hystrixdemo.utils;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;/*** @BelongsProject: hystrixDemo* @BelongsPackage: com.example.hystrixdemo.utils* @Author: Wuzilong* @Description: 注解解释器* @CreateTime: 2023-09-21 10:50* @Version: 1.0*/
@Aspect
@Component
public class MyAspect {Integer requestNum = 0;Date newTime = null;Date newDelayTime=null;Boolean isDelayTime = false;@AfterThrowing(pointcut = "execution(* com.example..*.*(..))",throwing = "ex")public Object afterThrowing(JoinPoint joinPoint,Exception ex) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {try {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();Method method1 = methodSignature.getMethod();if (method1.isAnnotationPresent(MyHystrixCommand.class)) {MyHystrixCommand annotation = method1.getAnnotation(MyHystrixCommand.class);MyHystrixProperty[] myHystrixProperties = annotation.commandProperties();if (myHystrixProperties.length == 0) {Method method2 = joinPoint.getTarget().getClass().getMethod(annotation.fallbackMethod());return method2.invoke(joinPoint.getTarget());} else {if (newDelayTime != null && new Date().compareTo(newDelayTime)>=0) {isDelayTime=false;newTime = null;newDelayTime=null;}if (isDelayTime) {Method method2 = joinPoint.getTarget().getClass().getMethod(annotation.fallbackMethod());method2.invoke(joinPoint.getTarget());} else {String numValue = null;String timeValue = null;String errorRateValue = null;String delayTimeValue = null;for (MyHystrixProperty property : myHystrixProperties) {if (property.name().equals("requestNum")) {numValue = property.value();} else if (property.name().equals("requestTime")) {timeValue = property.value();} else if (property.name().equals("requestErrorRate")) {errorRateValue = property.value();} else if (property.name().equals("requestDelayTime")) {delayTimeValue = property.value();}}requestNum++;if (newTime==null){// 创建Calendar对象,并设置为当前时间Calendar calendar = Calendar.getInstance();calendar.setTime(new Date());// 将Calendar对象的毫秒数加上任意值(这里假设增加1000毫秒)calendar.add(Calendar.MILLISECOND, Integer.valueOf(timeValue));newTime=calendar.getTime();}if (new Date().compareTo(newTime) >=0){if (requestNum >= Integer.valueOf(numValue)) {double i = Double.valueOf(numValue) / requestNum * 100;if (i >= Integer.valueOf(errorRateValue)) {isDelayTime = true;if (newDelayTime==null){// 创建Calendar对象,并设置为当前时间Calendar calendar = Calendar.getInstance();calendar.setTime(new Date());// 将Calendar对象的毫秒数加上任意值(这里假设增加1000毫秒)calendar.add(Calendar.MILLISECOND, Integer.valueOf(delayTimeValue));newDelayTime=calendar.getTime();}requestNum = 0;Method method2 = joinPoint.getTarget().getClass().getMethod(annotation.fallbackMethod());return method2.invoke(joinPoint.getTarget());}}}}}}} catch (Exception e) {System.out.println("通过异常进入到AOP中,调用了托底方法");}return null;}
}

  声明两个注解分别用来设置服务降级和熔断操作的。MyHystrixCommand注解中会指定降级的方法。其中也包括MyHystrixProperty注解来指定熔断操作开启的一些参数,例如请求的时间、请求的次数、请求错误率等等。MyAspect类去识别两个注解,处理对应的业务逻辑。

发送请求端

引入Hystrix的依赖

        <dependency><groupId>com.example</groupId><artifactId>hystrixDemo</artifactId><version>1.0-SNAPSHOT</version></dependency>

调用代码

package com.example.useraservice.service;import com.example.hystrixdemo.utils.MyHystrixCommand;
import com.example.hystrixdemo.utils.MyHystrixProperty;
import com.example.openfeigndemo.config.FeignConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @BelongsProject: UserAService* @BelongsPackage: com.example.useraservice.service* @Author: Wuzilong* @Description: 描述什么人干什么事儿* @CreateTime: 2023-07-26 08:40* @Version: 1.0*/
@Service
public class UserA {@Autowiredprivate FeignConfig feignConfig;@MyHystrixCommand(fallbackMethod = "errorMsg",commandProperties = {@MyHystrixProperty(name = "requestNum", value = "3"), //请求次数@MyHystrixProperty(name = "requestTime", value = "10000"), //请求的单位时间@MyHystrixProperty(name = "requestErrorRate", value = "50"),  //错误率@MyHystrixProperty(name = "requestDelayTime", value = "20000")   //熔断持续时间})public String userA(){System.out.println("进入A服务的方法了,去访问B服务。");IUserBService iUserBService=(IUserBService)feignConfig.getAgentObject();String returnContext = iUserBService.getServiceBInfo();System.out.println("B服务返回的内容是:"+returnContext);return "A服务调用B服务";}public String errorMsg()  {System.out.println("你有异常啦");return "你有异常了";}
}
package com.example.useraservice.controller;import com.example.useraservice.service.UserA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;/*** @BelongsProject: UserAService* @BelongsPackage: com.example.useraservice.controller* @Author: Wuzilong* @Description: 描述什么人干什么事儿* @CreateTime: 2023-07-26 15:44* @Version: 1.0*/
@RestController
@RequestMapping("/serviceA")
public class UserAController {@Autowiredprivate UserA userA;@RequestMapping(value="serviceAInfo",method= RequestMethod.GET)public void getServiceAInfo(){try{userA.userA();}catch (Exception e){System.out.println("通过异常进入到AOP中,已调用了托底方法");}}
}

接收请求端

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.net.InetAddress;
import java.net.UnknownHostException;/*** @BelongsProject: ServiceB* @BelongsPackage: com.example.serviceb.Controller* @Author: Wuzilong* @Description: B服务* @CreateTime: 2023-06-07 19:08* @Version: 1.0*/
@RestController
@RequestMapping("/B")
public class ServiceBController {@Value("${server.port}")private String serverPort;@GetMapping("/receiveMessage")public String receiveMessage() throws UnknownHostException {System.out.println("B:我被调用了");//返回的内容是ip地址和端口号return InetAddress.getLocalHost().getHostAddress()+":"+serverPort;}
}

执行效果

发送请求端

在这里插入图片描述  B服务没有启动,所以在请求的过程中或报错,由于配置了hystrix所以在报错的时候会进行降级或者熔断操作。

总结提升

  Hystrix是一个强大的工具,可以帮助开发人员处理分布式系统中的故障和延迟问题,提高系统的可用性和性能。它的各种功能和特点使得开发人员能够更好地控制和管理系统的运行状态,提供更好的用户体验。


🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯

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

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

相关文章

JAVA:实现Excel和PDF上下标

1、简介 最近项目需要实现26个小写字母的上下标功能,自己去网上找了所有Unicode的上下标形式,缺少一些关键字母,顾后面考虑自己创建上下标字体样式,以此来记录。 2、Excel Excel本身是支持上下标,我们可以通过Excel单元格的样式来设置当前字体上下标,因使用的是POI的m…

通过java向jar写入新文件

文章目录 原始需求分析实施步骤引入依赖核心编码运行效果 原始需求 有网友提问&#xff1a; 我想在程序中动态地向同一个jar包中添加文件&#xff0c;比如&#xff0c;我的可执行jar包是test.jar,我要在它运行时生成一些xml文件并将这些文件添加到test.jar中,请问如何实现&…

细胞机器人系统的概念

摘要 本文讨论了一种新型机器人系统的理论和工程的概念基础。该系统由协作完成任务的自主机器人单元组成。本文在描述了该系统与细胞自动机和神经网络的相关性和差异后&#xff0c;建立了该系统的基础属性及其对机器人单元结构的影响、它们操作的空间以及它们完成全局任务的算法…

【Ambari】银河麒麟V10 ARM64架构_安装Ambari2.7.6HDP3.3.1问题总结

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1f338;文…

如何快速学习AdsPower RPA(2)——中级、高级部分

Tool哥继续给大家分享快速学习AdsPower RPA的方法。上一篇在这里&#xff0c;还没看过的小伙伴赶快补课去&#xff1a;如何快速学习AdsPower RPA&#xff08;1&#xff09;——简单、进阶部分 能进入到中级、高级阶段的学习&#xff0c;说明你自学能力超强&#xff01;只要跟着…

java spring cloud 企业电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

编译原理简介

编译原理简介 编译原理的研究对于理解和设计编程语言、编译器和解释器都非常重要。它不仅可以提高程序的执行效率&#xff0c;还可以帮助开发人员更好地理解程序的运行机制。编译原理是计算机科学中的一个重要分支&#xff0c;研究的是编译器的设计和实现。对于从事编译器开发…

OpenGL之着色器

着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间唯一的沟通只有通过输入和…

开发模式-敏捷开发

1. 概述 随着软件开发技术的不断发展&#xff0c;现在出现了很多种不同的开发模式&#xff0c;其实敏捷开发已经成为现在很多企业开发应用程序都想要选择的开发方案&#xff0c;那么什么是敏捷开发呢&#xff1f; 1.1 四种开发模式 1.1.1 瀑布式开发 瀑布式开发是一种老旧的…

66种智能优化算法跑23个基准测试函数

目录 1、66种智能优化算法 2 、23个标准测试函数 3 、多种智能优化算法在CEC2005上对比 3.1、 多个算法对比 3.2 单个算法运行 1、66种智能优化算法 将66种智能优化算法在23个经典测试函数上进行对比&#xff0c;这些智能优化算法包括一些高性能算法&#xff0c;如…

软件测试/测试开发丨python 多态与super 学习笔记

本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/26828 python 多态与super 多态的概念 多态&#xff1a;Polymorphism 同名方法呈现多种行为 多态的表现 号 加法&#xff1a;数字 数字拼接&#xff1a;字符串 字符串合…

Spring基础与核心概念

Spring 是什么&#xff1f; 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃而庞大的社区&#xff0c;这就是它之所以能长久不衰的原因。Spring 支持广泛的应⽤场景&#xff0c;它可以让…

大数据Doris(一):Doris概述篇

文章目录 Doris概述篇 一、前言 二、Doris简介

Vue封装全局SVG组件

1.SVG图标配置 1.安装插件 npm install vite-plugin-svg-icons -D 2.Vite.config.ts中配置 import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from path export default () > {return {plugins: [createSvgIconsPlugin({// Specify the icon fo…

04. 人工智能核心基础 - 导论(3)

文章目录 人工智能和其他学科的关系为什么学习人工智能怎么学好人工智能&#xff1f;一些问题 Hi&#xff0c;你好。我是茶桁。 基于上一节课咱们的整体强度有点大&#xff0c;而且咱们马上也要进入高强度内容了&#xff0c;那么这一篇咱们就稍微水一篇吧。来聊聊天&#xff0…

FPGA 多路视频处理:图像缩放+视频拼接显示,HDMI采集,提供2套工程源码和技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐FPGA图像缩放方案推荐FPGA视频拼接方案推荐 3、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条缓冲FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 视频拼接算法图像缓存视频输出 4、vivado工程1&am…

【计算机网络】图解路由器(一)

本系列包含&#xff1a; 图解路由器&#xff08;一&#xff09;图解路由器&#xff08;二&#xff09; 图解路由器&#xff08;一&#xff09; 1、什么是路由器&#xff1f;2、什么是路由选择&#xff1f;3、什么是转发&#xff1f;4、路由器设备有哪些类型&#xff1f;5、根据…

【小笔记】fasttext文本分类问题分析

【学而不思则罔&#xff0c;思维不学则怠】 2023.9.28 关于fasttext的原理及实战文章很多&#xff0c;我也尝试在自己的任务中进行使用&#xff0c;是一个典型的短文本分类任务&#xff0c;对知识图谱抽取的实体进行校验&#xff0c;判断实体类别是否正确&#xff0c;我构建了…

高级时钟项目(2)Json文件解析学习---C语言版本

笔者来介绍一下json文件解析 1、背景介绍 笔者在获取天气数据的时候&#xff0c;是通过MCU的WIFI去获取&#xff0c;但是获取到的数据json数据&#xff0c;需要解析&#xff0c;C语言没那么解析库&#xff0c;所以就需要找一些开源的解析库。 笔者找到cjson这个适用于C语言…

【c语言】通讯录【动态版本:有排序和文件操作】

目录 一、通讯录定义 二、通讯录的实现 1、test.c中菜单的实现 2、通讯录的创建逻辑 3、初始化 4、检查容量和添加 5、查找 6、删除功能 7、修改功能 8、打印 9、查找并打印 10、qsort排序 11、摧毁 12、保存数据到文件 13、从文件中读数据 完整代码&#xff1a; 一、通讯录定…