Spring cloud - Hystrix源码

其实只是Hystrix初始化部分,我们从源码的角度分析一下@EnableCircuitBreaker以及@HystrixCommand注解的初始化过程。

从@EnableCircuitBreaker入手

我们是通过在启动类添加@EnableCircuitBreaker注解启用Hystrix的,所以,源码解析也要从这个注解入手。

该注解已经被标了@Deprecated了,不过,挡不住…

Spring关于@Enablexxxx注解的套路:通过@Import注解引入了EnableCircuitBreakerImportSelector.class:

@Deprecated
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {}

跟踪EnableCircuitBreakerImportSelector,继承自SpringFactoryImportSelector,注意SpringFactoryImportSelector类的泛型类型为EnableCircuitBreaker:

@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector extends SpringFactoryImportSelector<EnableCircuitBreaker> {@Overrideprotected boolean isEnabled() {return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE);}}

看一下类图:
在这里插入图片描述

属性annotationClass通过GenericTypeResolver.resolveTypeArgument方法获取当前对象的泛型参数的具体类型,现在我们知道是EnableCircuitBreaker(在org.springframework.cloud.client.circuitbreaker包下)。

public abstract class SpringFactoryImportSelector<T>implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware {private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class);private ClassLoader beanClassLoader;private Class<T> annotationClass;private Environment environment;@SuppressWarnings("unchecked")protected SpringFactoryImportSelector() {this.annotationClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(this.getClass(),SpringFactoryImportSelector.class);}

@Import注解我们前面做过详细分析了,实现了DeferredImportSelector接口表示延迟加载全限定名称为selectImports方法返回的类。看selectImports方法:

@Overridepublic String[] selectImports(AnnotationMetadata metadata) {//Enable参数没有打开的话就不加载if (!isEnabled()) {return new String[0];}AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(this.annotationClass.getName(), true));Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName()+ " annotated with @" + getSimpleName() + "?");// Find all possible auto configuration classes, filtering duplicates//SPI机制调用spring.factories文件下的EnableCircuitBreakerList<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader)));if (factories.isEmpty() && !hasDefaultFactory()) {throw new IllegalStateException("Annotation @" + getSimpleName()+ " found, but there are no implementations. Did you forget to include a starter?");}if (factories.size() > 1) {// there should only ever be one DiscoveryClient, but there might be more than// one factorythis.log.warn("More than one implementation " + "of @" + getSimpleName()+ " (now relying on @Conditionals to pick one): " + factories);}return factories.toArray(new String[factories.size()]);}

selectImports方法的主要功能就是调用SpringFactoriesLoader.loadFactoryNames方法,该方法的目的是通过SPI机制读取spring.factories文件中的org.springframework.cloud.client.circuitbreaker相关配置,返回。

返回的信息是类全限定名,从selectImports方法作用可知,这些类会加载到Spring Ioc容器中。

org.springframework.cloud.client.circuitbreaker在spring-cloud-netflix-hystrix-2.2.10.RELEASE包下:
org.springframework.cloud.client.circuitbreaker
所以该配置下的org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration会被调用并加载到Spring IoC容器中。

HystrixCircuitBreakerConfiguration

跟踪配置类HystrixCircuitBreakerConfiguration:


/*** @author Spencer Gibb* @author Christian Dupuis* @author Venil Noronha*/
@Configuration(proxyBeanMethods = false)
public class HystrixCircuitBreakerConfiguration {@Beanpublic HystrixCommandAspect hystrixCommandAspect() {return new HystrixCommandAspect();}@Beanpublic HystrixShutdownHook hystrixShutdownHook() {return new HystrixShutdownHook();}

注入了一个叫HystrixCommandAspect 的bean,从名字上看,应该是关于HystrixCommand的切面,用到了AOP。其实也容易理解,加了@HystrixCommand注解的方法的执行逻辑发生了变化:方法增强了执行时长是否超时、执行是否成功(是否返回异常)、超时或异常的情况下调用fallback…方法功能的增强正是AOP的强项。

继续跟踪HystrixCommandAspect 类。

HystrixCommandAspect

打开代码,首先是非常熟悉的@Aspect注解:

@Aspect
public class HystrixCommandAspect {

表明当前类是AOP的切面。

继续看代码:

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")public void hystrixCommandAnnotationPointcut() {}@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")public void hystrixCollapserAnnotationPointcut() {}@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {

添加了针对注解HystrixCommand的切点,以及针对该切点的环绕增强方法methodsAnnotatedWithHystrixCommand。

最终的熔断、限流、服务降级功能,都是在这个methodsAnnotatedWithHystrixCommand方法里实现的,继续向下研究这个方法的代码逻辑,需要RxJava背景知识做支撑。

有空再聊:) ~!

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

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

相关文章

最新PHP熊猫头图片表情斗图生成源码

这是一款能生成熊猫头表情斗图的自适应系统源码&#xff0c;无论是在电脑还是手机上都可以正常使用&#xff01;这个源码集成了搜狗搜索图片接口&#xff0c;可以轻松地一键搜索数百万张图片&#xff0c;并且还包含了表情制作等功能模块。对于一些新站来说&#xff0c;这是一个…

JavaScript的过滤大师:深度解析Filter用法

JavaScript的过滤大师&#xff1a;深度解析Filter用法 前言基础篇filter的基本用法语法示例 自定义过滤函数数组对象的过滤复杂条件的筛选常见应用场景性能优化注意性能的建议在大规模数据集下的优化方法 案例分析实际案例&#xff1a;用户筛选使用 filter 方法解决问题代码优化…

产品工程师工作的职责十篇(合集)

一、岗位职责的作用意义 1.可以最大限度地实现劳动用工的科学配置; 2.有效地防止因职务重叠而发生的工作扯皮现象; 3.提高内部竞争活力&#xff0c;更好地发现和使用人才; 4.组织考核的依据; 5.提高工作效率和工作质量; 6.规范操作行为; 7.减少违章行为和违章事故的发生…

好视通视频会议系统(fastmeeting) toDownload.do接口存在任意文件读取漏洞复现 [附POC]

文章目录 好视通视频会议系统(fastmeeting) toDownload.do接口存在任意文件读取漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 好视通视频会议系统(fastmeeting) toDownload.do接口存在任意文件…

超详细!新手必看!STM32-通用定时器简介与知识点概括

一、通用定时器的功能 在基本定时器功能的基础上新增功能&#xff1a; 通用定时器有4个独立通道&#xff0c;且每个通道都可以用于下面功能。 &#xff08;1&#xff09;输入捕获&#xff1a;测量输入信号的周期和占空比等。 &#xff08;2&#xff09;输出比较&#xff1a;产…

Gradle常用命令与参数依赖管理和版本决议

一、Gradle 常用命令与参数 本课程全程基于 Gradle8.0 环境 1、Gradle 命令 介绍 gradle 命令之前我们先来了解下 gradle 命令怎么在项目中执行。 1.1、gradlew gradlew 即 Gradle Wrapper&#xff0c;在学习小组的第一课时已经介绍过了这里就不多赘述。提一下执行命令&am…

.Net6使用WebSocket与前端进行通信

1. 创建类WebSocketTest&#xff1a; using System.Net.WebSockets; using System.Text;namespace WebSocket.Demo {public class WebSocketTest{//当前请求实例System.Net.WebSockets.WebSocket socket null;public async Task DoWork(HttpContext ctx){socket await ctx.We…

为UE和Unity开发者准备的Godot指南

为UE和Unity开发者准备的Godot指南 ——两位大哥打架&#xff0c;请带上我 这两天游戏行业又开始热闹了&#xff0c;昨天两条信息直接刷爆朋友圈&#xff0c;最大的两家游戏引擎公司怼起来了。 《为Unity开发者准备的虚幻引擎指南》&#xff1a; 为Unity开发者准备的虚幻引擎指…

sso 四种授权模式

单点登录 单点登录&#xff0c;英文是 Single Sign On&#xff08;缩写为 SSO&#xff09;。即多个站点共用一台认证授权服务器&#xff0c;用户在站点登录后&#xff0c;可以免登录访问其他所有站点。而且&#xff0c;各站点间可以通过该登录状态直接交互。例如&#xff1a; …

还记得高中生物书上的莫斯密码吗?利用Python破解摩斯密码的代码示例!

文章目录 前言摩尔斯电码Python实现摩斯密码对照表加密解密测试 完整代码总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Py…

一文读懂 Linux mmap

文章目录 1.简介2.实现原理3.相关函数4.mmap和常规文件操作的区别5.作用参考文献 1.简介 mmap&#xff08;memory map&#xff09;即内存映射&#xff0c;用于将一个文件或设备映射到进程的地址空间。 实现这样的映射关系后&#xff0c;进程虚拟地址空间中一段内存地址将与文…

逐字节讲解 Redis 持久化(RDB 和 AOF)的文件格式

前言 相信各位对 Redis 的这两种持久化机制都不陌生&#xff0c;简单来说&#xff0c;RDB 就是对数据的全量备份&#xff0c;AOF 则是增量备份&#xff0c;而从 4.0 版本开始引入了混合方式&#xff0c;以 7.2.3 版本为例&#xff0c;会生成三类文件&#xff1a;RDB、AOF 和记…

2014年5月28日 Go生态洞察:GopherCon 2014大会回顾

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

如何让Python2与Python3共存

安装 首先分别安装Py2和Py3&#xff0c;我都安装到C盘根目录里了&#xff0c;然后分别将Py2和Py3都配置到系统环境变量中去&#xff1a;C:\Python36\Scripts\;C:\Python36\;C:\Python27\;C:\Python27\Scripts; 配置 修改两个版本的可执行文件名字 验证 重新配置一下pip …

Ubuntu删除应用图标

删除用户下的图标 sudo nautilus ~/.local/share/applications删除系统下的图标 sudo nautilus /usr/share/applications

uni-app 使用uni.getLocation获取经纬度配合腾讯地图api获取当前地址

前言 最近在开发中需要根据经纬度获取当前位置信息&#xff0c;传递给后端&#xff0c;用来回显显示当前位置 查阅uni-app文档&#xff0c;发现uni.getLocation () 可以获取到经纬度&#xff0c;但是在小程序环境没有地址信息 思考怎么把经纬度换成地址&#xff0c;如果经纬度…

buildadmin+tp8表格操作(1)----表头上方添加按钮和自定义按钮

buildAdmin 的表头上添加一些按钮&#xff0c;并实现功能 添加按钮 <template><!-- buttons 属性定义了 TableHeader 本身支持的顶部按钮&#xff0c;仅需传递按钮名即可 --><!-- 这里的框架自带的 顶部按钮 分别有 刷新 &#xff0c; 添加&#xff0c; 编辑&…

C++ 问题 怎么在C++11标准语法中调用C++20的类

一. 问题 在工作中,因为一个算法功能需要跟别的部门对接,他们提供了该算法的头文件.h,静态库.lib,动态库.dll。但是头文件中使用了C++20才有的新特性,如#include等,而本地使用的vs2015开发环境,只支持C++11标准语法,这种情况下,该怎么把该算法集成到本地项目中呢? …

写单元测试,没你想得那么简单!

前言 单元测试是什么我们就简单介绍一下&#xff1a; 单元测试是针对程序模块&#xff08;软件设计的最小单位&#xff09;来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。 接下来是本人对单元测试的理解和实践。里面没有废话&#xff0c;希望每句话能说到你心…

YOLOv8改进实战 | 更换主干网络Backbone(六)之轻量化模型VanillaNet进阶篇

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…