微服务-@FeignClient 与 Feign 隔离

FeignClient 扫描

在这里插入图片描述
FeignClientsRegistrar#registerBeanDefinitions

public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
// 注册默认配置
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}

/**
*  默认配置描述如下* A custom <code>@Configuration</code> for all feign clients. Can contain override* <code>@Bean</code> definition for the pieces that make up the client, for instance* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.** @see FeignClientsConfiguration for the defaults* @return list of default configurations*/
Class<?>[] defaultConfiguration() default {};

FeignClientsRegistrar#registerFeignClients

ClassPathScanningCandidateComponentProvider scanner = getScanner();scanner.setResourceLoader(this.resourceLoader);scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));Set<String> basePackages = getBasePackages(metadata);for (String basePackage : basePackages) {// 获取候选类 被FeignClient标注			candidateComponents.addAll(scanner.findCandidateComponents(basePackage));}

FeignClientsRegistrar#registerClientConfiguration
FeignClientsRegistrar#registerFeignClient

// 这段逻辑会在真正获取对象的时候调用
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {factoryBean.setUrl(getUrl(beanFactory, attributes));factoryBean.setPath(getPath(beanFactory, attributes));factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));Object fallback = attributes.get("fallback");if (fallback != null) {factoryBean.setFallback(fallback instanceof Class? (Class<?>) fallback: ClassUtils.resolveClassName(fallback.toString(), null));}Object fallbackFactory = attributes.get("fallbackFactory");if (fallbackFactory != null) {factoryBean.setFallbackFactory(fallbackFactory instanceof Class? (Class<?>) fallbackFactory: ClassUtils.resolveClassName(fallbackFactory.toString(),null));}// 获取实例对象的核心逻辑return factoryBean.getObject();});definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);definition.setLazyInit(true);validate(attributes);

我们断点打在factoryBean.getObject() 追进去

return (T) loadBalance(builder, context,new HardCodedTarget<>(type, name, url));

然后继续往下走:HystrixTargeter -> Feign -> ReflectiveFeign

public <T> T newInstance(Target<T> target) {Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();for (Method method : target.type().getMethods()) {if (method.getDeclaringClass() == Object.class) {continue;} else if (Util.isDefault(method)) {DefaultMethodHandler handler = new DefaultMethodHandler(method);defaultMethodHandlers.add(handler);methodToHandler.put(method, handler);} else {methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));}}InvocationHandler handler = factory.create(target, methodToHandler);// JDK 动态代理创建了真正的对象  handler类为HystrixInvocationHandler implements InvocationHandlerT proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler);for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {defaultMethodHandler.bindTo(proxy);}return proxy;}

调用的时候

 HystrixCommand<Object> hystrixCommand =new HystrixCommand<Object>(setterMethodMap.get(method)) {@Overrideprotected Object run() throws Exception {try {// 这里真正的去调用远程方法return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);} catch (Exception e) {throw e;} catch (Throwable t) {throw (Error) t;}}// 这里是异常处理@Overrideprotected Object getFallback() {if (fallbackFactory == null) {return super.getFallback();}try {Object fallback = fallbackFactory.create(getExecutionException());Object result = fallbackMethodMap.get(method).invoke(fallback, args);if (isReturnsHystrixCommand(method)) {return ((HystrixCommand) result).execute();} else if (isReturnsObservable(method)) {// Create a cold Observablereturn ((Observable) result).toBlocking().first();} else if (isReturnsSingle(method)) {// Create a cold Observable as a Singlereturn ((Single) result).toObservable().toBlocking().first();} else if (isReturnsCompletable(method)) {((Completable) result).await();return null;} else if (isReturnsCompletableFuture(method)) {return ((Future) result).get();} else {return result;}} catch (IllegalAccessException e) {// shouldn't happen as method is public due to being an interfacethrow new AssertionError(e);} catch (InvocationTargetException | ExecutionException e) {// Exceptions on fallback are tossed by Hystrixthrow new AssertionError(e.getCause());} catch (InterruptedException e) {// Exceptions on fallback are tossed by HystrixThread.currentThread().interrupt();throw new AssertionError(e.getCause());}}};

在这里插入图片描述
我们在调用的时候在选择实例NacosNamingService#selectInstances,发现会选择实例,这就是 OpenFeign 首次发起远程调用时,会很慢的原因。
在这里插入图片描述

Feign 隔离

在这里插入图片描述
源代码
org.springframework.cloud.openfeign.FeignClientFactoryBean#get

org.springframework.cloud.context.named.NamedContextFactory#getInstance

public <T> T getInstance(String name, Class<T> type) {AnnotationConfigApplicationContext context = getContext(name);try {return context.getBean(type);}catch (NoSuchBeanDefinitionException e) {// ignore}return null;
}

org.springframework.cloud.context.named.NamedContextFactory#getContext

protected AnnotationConfigApplicationContext getContext(String name) {if (!this.contexts.containsKey(name)) {synchronized (this.contexts) {if (!this.contexts.containsKey(name)) {this.contexts.put(name, createContext(name));}}}return this.contexts.get(name);
}

org.springframework.cloud.context.named.NamedContextFactory#createContext

protected AnnotationConfigApplicationContext createContext(String name) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();if (this.configurations.containsKey(name)) {for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {context.register(configuration);}}for (Map.Entry<String, C> entry : this.configurations.entrySet()) {if (entry.getKey().startsWith("default.")) {for (Class<?> configuration : entry.getValue().getConfiguration()) {context.register(configuration);}}}context.register(PropertyPlaceholderAutoConfiguration.class,this.defaultConfigType);context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,Collections.<String, Object>singletonMap(this.propertyName, name)));if (this.parent != null) {// Uses Environment from parent as well as beanscontext.setParent(this.parent);// jdk11 issue// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101context.setClassLoader(this.parent.getClassLoader());}context.setDisplayName(generateDisplayName(name));// 重点在这里,创建了一个迷你的上下文对象,并且刷新了迷你上下文对象进行实例化操作 这会影响OpenFeing的效率变慢context.refresh();return context;}

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

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

相关文章

服务异步通讯---RabbitMQ实用篇

目录 一、初识MQ 一、同步调用 1、同步通讯和异步通讯 2、同步调用的问题 3.同步调用总结 二、异步调用 1、优势&#xff1a; ​编辑 2、异步总结 二、什么是MQ 一、RabbitMQ快速入门 1、RabbitMQ的结构和概念 2、常见消息模型 2.1、基础消息队列模型 2.2、总结 二…

Sharding-JDBC快速使用【笔记】

1 引言 最近在使用Sharding-JDBC实现项目中数据分片、读写分离需求&#xff0c;参考官方文档&#xff08;Sharding官方文档&#xff09;感觉内容庞杂不够有条理&#xff0c;重复内容比较多&#xff1b;现结合项目应用整理笔记如下供大家参考和自己回忆使用&#xff1b; 在…

为什么要太空探索?未来万亿人口 人类移居太空是不可避免的。大语言模型是发现 贝索斯

管理的思考 「最以客户为中心」「果断」「如何决策」 贝索斯给亚马逊的使命是「世上最以客户为中心的公司」(以客户需求为起点&#xff0c;反向推动工作)。贝索斯给蓝色起源的使命是「世上最果断的公司」(我们将变得非常擅长在技术上恰当地冒险&#xff0c;并快速地作出那些决…

性能检测自动化(含内存泄露检测)

一、平台侧实现方案 1、UI case重复执行N次:进入页面,sleep 5s,记录start_time,sleep 30s,记录end_time,性能采集工具全程采集性能数据 2、根据采集到的性能数据,按照N次卡点性能数据:去掉最大的10%、最小的10%,求取平均值,作为单次性能数据结果f(n)…

基于springboot的校园社团信息管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的校园社团信息管理系统,…

一篇了解springboot3请求参数种类及接口测试

SpringBoot3数据请求&#xff1a; 原始数据请求&#xff1a; //原始方式RequestMapping("/simpleParam")public String simpleParam(HttpServletRequest request){//获取请求参数String name request.getParameter("name");String age request.getParame…

钉钉-蓝牙打卡和平台打卡的区别

钉钉的群是部门概念。 你的账号归属到哪个群&#xff0c;就是哪个群的员工。 -------------------------------------------------------------------- 蓝牙打卡是对账号归属进行打卡的。 平台打卡是只对属于自己平台内的账号打卡的。 ----------------------------------…

193.【2023年华为OD机试真题(C卷)】手机App防沉迷系统(贪心算法—JavaPythonC++JS实现)

请到本专栏顶置查阅最新的华为OD机试宝典 点击跳转到本专栏-算法之翼:华为OD机试 🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 【2023年华为OD机试真题(C卷)】手机App防沉迷系统(…

【MATLAB】PSO粒子群优化BiLSTM(PSO_BiLSTM)的时间序列预测

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 基于PSO粒子群优化的BiLSTM的时间序列预测算法的基本原理如下&#xff1a; 「双向长短时记忆&#xff08;BiLSTM&#xff09;模型」&#xff1a;这是一种深度学习模型&#xff0c;特别适用…

感恩客户相伴23载,泛微2024持续向上!

2023年&#xff0c;国家大力推动数字经济发展&#xff0c;各行各业在加速数字化转型&#xff0c;在这一年&#xff0c;泛微保持持续增长&#xff0c;引领行业发展&#xff0c;为组织的数字化转型助力。感恩客户与伙伴朋友的支持与信任&#xff01; 01.泛微中大客户总量突破8万余…

Unity中Shader的Reversed-Z(DirectX平台)

文章目录 前言一、在对裁剪坐标归一化设置NDC时&#xff0c;DirectX平台Z的特殊二、在图形计算器中&#xff0c;看一下Z值反转前后变化1、在图形计算器创建两个变量 n 和 f 分别 控制近裁剪面 和 远裁剪面2、带入公式得到齐次裁剪空间下Z值3、进行透视除法4、用 1 - Z 得出Z值反…

VS+QT五子棋游戏开发

1、首先安装好VS软件和QT库&#xff0c;将其配置好&#xff0c;具体不在此展开说明。 2、文件结构如下图&#xff1a; 3、绘制棋盘代码&#xff0c;如下&#xff1a; void Qwzq::paintEvent(QPaintEvent* event) {QPainter painter(this);painter.setRenderHint(QPainter::An…

【响应式编程-01】Lambda表达式初体验

一、简要描述 Lambda初体验Lambda表达式的语法格式Lambda表达式应用举例Lambda表达式底层实现 二、什么是Lambda表达式 Java8新特性&#xff0c;来源于数学中的λ[l:mdə]演算 是一套关于函数(f(x))定义、输入量、输出量的计算方案 Lambda表达式 -> 函数 使代码变得简洁…

维生素B5和琥珀酰辅酶A可以改善SF3B1基因突变引起无效造血过程

今天给同学们分享一篇实验文章“Vitamin B5 and succinyl-CoA improve ineffective erythropoiesis in SF3B1-mutated myelodysplasia”&#xff0c;这篇文章发表在Sci Transl Med期刊上&#xff0c;影响因子为17.1。 结果解读&#xff1a; SF3B1突变导致MDS-RS患者COASY异构体…

短视频账号矩阵系统源码/技术交付3年开发源头

账号矩阵3年技术独立开发打造是一个非常有挑战性和前景的项目。以下是一些建议&#xff0c;帮助你成功打造一个成功的短视频账号矩阵&#xff1a; 1. 确定目标受众&#xff1a;首先需要明确你的目标受众是谁&#xff0c;了解他们的兴趣爱好、年龄、性别等&#xff0c;以便为他们…

易点易动设备管理系统:提升化工企业设备巡检效率的利器

在化工企业中&#xff0c;设备巡检是确保设备正常运行和生产安全的重要环节。然而&#xff0c;传统的人工巡检方式存在效率低下、易出错等问题。为了解决这些问题&#xff0c;易点易动设备管理系统应运而生。本文将介绍易点易动设备管理系统如何帮助化工企业提升设备巡检效率&a…

【大数据实战】聊聊clickhouse的性能问题-高性能分析

聊聊ck的性能问题 在OLAP的查询场景中&#xff0c;同样的数据量&#xff0c;ClickHouse表现出了比同类可比较产品更优的性能。 查看Yandex的内部测试结果&#xff1a;结果 可以看到CK在OLAP场景下的性能还是非常强的&#xff0c;那么是不是它在每个指标上表现都很好呢&#x…

八大算法排序@选择排序(C语言版本)

目录 选择排序概念算法思想示例步骤1步骤2步骤...n最后一步 代码实现时间复杂度空间复杂度特性总结 选择排序 概念 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。基本思想是在未排序的序列中找到最小&#xff08;或最大&#xff09;元素&#xf…

RS485数据采集模块,如何一次采集多个modbus设备数据?

在工业数据采集中&#xff0c;RS485是一种常见的数据通信协议&#xff0c;而Modbus则是其上的常用设备协议。那么&#xff0c;如何用一个模块高效采集多个Modbus设备的数据呢&#xff1f;这就是我们今天要探讨的话题&#xff01; 什么是RS485数据采集模块&#xff1f; 首先&a…

ALSA学习(5)——设备中的alsa

参考博客&#xff1a; https://blog.csdn.net/DroidPhone/article/details/7165482 &#xff08;一下内容基本是原博主的博客转载&#xff09; 文章目录 一、ASOC的由来二、硬件架构三、软件架构四、数据结构五、内核对ASoC的改进 一、ASOC的由来 ASoC–ALSA System on Chip …