feign原理详解_vip视频解析是什么原理

feign原理详解_vip视频解析是什么原理Feign原理解析基本原理现在已经了解了Ribbon的负载均衡原理,我们可以来猜想下,Feign的原理,仅仅通过一个注解@FeignClient+一个接口,就可以服务之间的调用。通过@FeignClient在注解中的name,确定服务名,然后RibbonClient使用服务名去获取负载均衡器loadBalancer,再通过负载均衡算法获取到ip:port,然后构建的请求为http://nacos-component-provider/test/{id},当id=1

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

Feign 原理解析

基本原理

现在已经了解了 Ribbon 的负载均衡原理,我们可以来猜想下,Feign 的原理,仅仅通过一个注解 @FeignClient + 一个接口,就可以服务之间的调用。

  • 通过 @FeignClient 在注解中的name,确定服务名,然后 RibbonClient 使用服务名去获取负载均衡器 loadBalancer,再通过负载均衡算法获取到 ip:port, 然后构建的请求为 http://nacos-component-provider/test/{id},当 id = 1时,最后通过参数封装等,请求为http://nacos-component-provider/test/1,然后进行服务名替换,http://ip:port/test/1。这个就是最终的请求,也是 @FeignClient 注解的作用。
  • 那么就需要看下接口的作用了,定义了一个接口,肯定是不能调用接口的方法的,需要有实现类,这时候就就会通过代理,反射生成一个代理类,最后执行最终生成的请求。
/** * 定义一个REST风格的请求接口,如果 ribbon 可用,它将具备负载均衡的功能。 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient { 
   
    // 一般为服务名
	@AliasFor("name")
	String value() default "";
}

//例子,构造的请求最终会是: http://nacos-component-provider/test/{id}
@FeignClient(value = "nacos-component-provider")
public interface ProviderClient { 
   
    @GetMapping("test/{id}")
    String test(@PathVariable("id") Integer id);
}

Feign 初始化

要想使用 Feign,就首先需要加上 @EnableFeignClients 注解开启 Feign功能,然后创建接口和调用方法,接着加上注解 @FeignClient 就可以进行使用了。

  1. 首先 @EnableFeignClients 注解是怎么开启 Feign 功能的,可以看到注解上 @Import FeignClientsRegistrar (feign client 注册类), 将扫描后的接口注册。
//扫描我们定义的包路径(默认为@SpringBootApplication类所在的包)下带有 @FeignClient 注解的接口,然后将这些接口注册为 feign clients 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients { 
   

    //扫描的包路径
	String[] value() default { 
   };

	// 扫描的包路径
	String[] basePackages() default { 
   };
}
  1. 进入 FeignClientsRegistrar,查看 registerBeanDefinitions ,这里是使用了 @EnableFeignClients,那么这里是注册的核心逻辑
    feign原理详解_vip视频解析是什么原理

  2. 将 @FeignClient 注解的接口解析接口和注解的配置信息,包装为 一个 FeignClientFactoryBean 工厂 bean ,注册进 spring 的 beanDefinationMap中。
    feign原理详解_vip视频解析是什么原理

  3. 看到这里发现只是简单的将 beanDefinition 信息注册进 beanMap,但是还没有真正实例化,那么到底是在哪里实例化的呢?由于这个 bean 是 FeignClientFactoryBean,那么肯定是这个 bean 工厂进行创建的,进入这个类。发现一个重载的 getObject 方法,很明显这个是创建 bean 的方法,肯定是有人依赖 FeignClientBean 也就是我们这里的 ProviderClient,当被自动注入时,就会去获取getBean(ProviderClient.class) 方法,接着就会调用 bean 工厂去创建 bean。下图就是 IOC 的实际运行情况。
    feign原理详解_vip视频解析是什么原理

  4. 接着就会调用 FeignClientFactoryBean#getObject() 中创建 bean ,进入 getObject(),然后调用了 getTarget(),从 spring 容器中获取了 FeignContext 对象,可以看一下 FeignContext 什么时候注入的,发现在 FeignAutoConfiguration#feignContext() 就进行注入了,也就是 springboot 加载时,就实例化好了。FeignContext 官方注释:给每一个 client 都具有设置一个 springApplicationContext的属性,方便每个 client 获取需要的 bean。简单来说就是每个client 都可以具备 springApplicationContext 的功能。

  5. 使用 FeignContext 构造 Feign.Builder构造器,看名字可以知道就是生成 feiclient 的构造器,将需要的参数进行封装,此时的 ProviderClient 接口的调用url的前缀为:http://nacos-component-provider
    feign原理详解_vip视频解析是什么原理

  6. 调用 loadBalance() 方法,构造了 HystrixTargeter 对象,然后调用 HystrixTargeter#target 方法,发现这里调用了 Feign#target, 这里就是通过反射将之前的 Feign.Builder 创建出来代理对象,但是还有 ProviderClient 中的方法的 springmvc 的 @RequestMapping 等注解没有解析。
    feign原理详解_vip视频解析是什么原理

  7. 执行 build()方法,主要是构建配置hystrix集成所需的组件 ReflectiveFeign 对象,然后执行构建代理 bean 的核心方法newInstance(target)。

// build() 构造配置hystrix集成所需的组件 ReflectiveFeign,然后再实例化最终的 bean 对象
public <T> T target(Target<T> target) { 
   
	return build().newInstance(target);
}
  1. 首先通过反射获取 ProviderClient 类中的所有方法,构建为 ProviderClient#test() 为key,value为对应的 methodHandler 形式的 map,其中 methodHandler 具有一个负载均衡客户端 LoadBalancerFeignClient ,用于后面使用 LoadBalancerFeignClient 调用方法,这里是为了后面获取 method上注解的属性,例如 url,httpMethod 等属性准备。
    feign原理详解_vip视频解析是什么原理

  2. 使用 jdk动态代理,创建完成代理 bean,其中 InvocationHandler 就是最终的调用方,它包括了 ProviderClient 的方法处理器等信息。到这里就是给 ProviderClient 接口构建了个代理对象,然后使用代理对象进行服务的调用。为什么用 jdk动态代理呢?很简单呀,因为这是一个接口,jdk 生成代理对象则必须要实现一个接口。
    feign原理详解_vip视频解析是什么原理

  3. 当调用 ProviderClient#test 方法时,观察注入的 ProviderClient,就是我们上一步生成好的代理对象,然后调用 ReflectiveFeign#invoke() 实现对方法的调用。
    feign原理详解_vip视频解析是什么原理

  4. 根据调用的方法,使用 dispatch 调用对应的 methodHandler,dispatch 就是之前构造代理对象中的方法映射 map,然后调用 SynchronousMethodHandler#invoke() 方法,根据方法上的注解信息 value=“test/{id}”、参数id=1,创建 RequestTemplate 对象,其中 URI=test/1。
    feign原理详解_vip视频解析是什么原理
    feign原理详解_vip视频解析是什么原理

  5. 使用 LoadBalancerFeignClient执行 request 请求,此时请求已经是一个完整的请求,调用LoadBalancerFeignClient#execute 执行请求的替换和请求调用。
    feign原理详解_vip视频解析是什么原理

  6. 通过服务名构建一个 FeignLoadBalancer(其中就是一个ZoneAwareLoadBalancer)动态获取 nacos 上服务名对应的注册的所有服务,然后再进行服务的选取,例如轮询、随机等负载均衡策略,默认是轮询可用的服务列表。
    feign原理详解_vip视频解析是什么原理

  7. 将获取到的服务 server 和旧的uri,进行组装,获取一个最终请求的uri,然后进行请求调用。使用默认的 Client#execute 执行 http 请求调用,然后获取结果,将返回结果进行处理。这就是 feignClient 的调用流程。
    feign原理详解_vip视频解析是什么原理
    feign原理详解_vip视频解析是什么原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185874.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QT3D场景的快速绘制

    QT3D场景的快速绘制    QT3D场景提供了一种快速设置3D场景的一种方式,用户凭借着封装好的实体可以快速的在顶层实体(画布)当中增加各种各样的实体,并且通过3DMax软件构造的OBJ文件与QT3D实现信息交互可以的帮助用户摆脱OpenGL的用代码绘制图形的繁琐。本人在做这方面的工作时也看了很多来自CSDN的文章,但是直接将封装好的3D实体放入画布的例子有点少(是不是大家觉得太简单了?),所以作为一个QT3D建模…

    2022年6月4日
    26
  • 项目管理-5大过程组-10大知识领域-47过程

    项目管理五大过程组:1、启动过程组:获得授权,定义一个新项目或现有项目的一个新阶段,正式开始该项目或阶段的一组过程。2、规划过程组:明确项目范围,优化目标,为实现目标而制定行动方案的一组过程。3、执行过程组:完成项目管理计划中确定的工作以实现项目目标的一组过程。4、监控过程组:跟踪、审查和调整项目进展与绩效,识别必要的计划变更并启动相应变更的一组过程。5、收尾过程组:为完结所有过程组的…

    2022年4月13日
    48
  • social engineering databese_social engineering attack

    social engineering databese_social engineering attack请不要用于非法用途!!!(全部搜集自互联网,作者不负法律责任,不能保证可用性)QQ群:https://qqgroup.insight-labs.orghttps://s3.amazonaws.com/qqqun./index.html(与insight-labs类似)www.weigongkai.comhttp://qun.594sgk.c…

    2022年10月5日
    0
  • 51单片机LCD1602程序详解[通俗易懂]

    51单片机LCD1602程序详解[通俗易懂]LCD1602工业字符型液晶。1602是指LCD显示的内容为16X2,即可以显示两行,每行16个字符.特殊接口说明RS:寄存器选择输入端RS=1:指向数据寄存器RS=0:指向指令寄存器RW:读写控制输入端RW=0:写操作RW=1:读操作E:使能信号输入端读操作时,高电平有效;写操作时,下降沿有效;程序编写:#include#inc

    2022年7月16日
    12
  • post请求406,not acceptable问题[通俗易懂]

    最近在做一个项目,发现自己从ajax发送请求后返回的json数据接收不到,后台没有报错,经测试ajax的seccess内代码没有走,打开浏览器控制台一看,报错post:406not acceptable,接收后台传输过来响应的type为text/html。上网查找类似问题,总结如下:1、@responsebody标签没有加。那么返回的内容会经过视图解析器,加上标签后返回的数据会直接写入到…

    2022年4月9日
    55
  • 电平转换实现简述_为什么要进行电平转换

    电平转换实现简述_为什么要进行电平转换电平转换实现简述1.前言2.BJT和mos实现3.二极管实现4.电阻实现1.前言在设计电路时,很多情况下会出现电平不匹配的情况,最常用的方式就是增加电平转换芯片。那自然就会想到其实现思想源自于哪?如果用分离器件搭,如何能实现?下图是SN74ALVC164245的逻辑框图,包含与门和反相器,与门主要实现使能和方向控制,反向器用来实现信号传输。2.BJT和mos实现以NPN的BJT和NMOS为例来说,集电极输出和漏极输出是最简单的反相器。只不过由于BJT和MOS本身的特性,BJT只能单向传输

    2022年8月10日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号