(一)Springcloud-OpenFeign原理之集成改造原生Openfeign与简单使用

news2024/10/5 16:19:28

文章目录

  • 1.和原生Openfeign的关系
  • 2.Springcloud-Openfeign的改造
    • 2.1 改造目标
    • 2.2 改造内容
      • 2.2.1 集成到Spring
      • 2.2.2 替换构造组件
    • 2.3 初步集成使用
    • 2.4 支持的扩展点

文章将会介绍Springcloud-Openfeign对原生Openfeign的改造原因及方式,最后提供简单的使用案例及扩展点分析,需要提前了原生Openfeign和Spring容器的相关原理

1.和原生Openfeign的关系

原生Openfeign指的是io.github.openfeign,前身是Netflix的Feign项目,不是Springcloud体系中的springcloud-openfeign。原生的Openfeign凭借其合理的抽象设计,大大增强了框架的可扩展性,springcloud-openfeign正是基于框架的可扩展性,替换其核心的几个组件,让Feign支持解析SpringMVC注解,且动态代理对象由FactoryBean接口完成构造,进而完美的集成到Spring体系中。

关于原生OpenFeign如何优化HTTP调用流程并抽象对应组件跳至该文章阅读:原生OpenFeign相较于传统HTTP工具的优化和原理

只有了解了原生Openfeign的实现原理及核心组件的作用后看本篇文章才有意义。

2.Springcloud-Openfeign的改造

2.1 改造目标

如果要知道Springcloud-Openfeign对原生的Openfeign做了什么改造,就需要知道Springcloud-Openfeign想要达到的目标是什么。

Springcloud引入改造Openfeign目的有三:

  1. Springcloud体系缺乏一款灵活轻便且扩展性高的RPC框架;
  2. 经过改造后容易集成到Spring容器中;
  3. 引入的RPC框架可以兼容SpringMVC注解以降低RPC的学习成本和使用便利性。

而引入Openfeign刚好满足Springcloud的三个目的:

  1. Openfeign由于抽象出各个功能组件,因此可扩展性和灵活性极高;
  2. Openfeign采用了类似于Mybatis的JDK动态代理,使用接口就可以生成代理对象,轻便且容易集成到Spring容器中管理;
  3. Openfeign使用Contract协议组件去解析接口方法的注解,如果要支持SpringMVC的注解,只需要实现解析SpringMVC注解的组件,并用其替换Openfeign的Contract组件即可实现编写SpringMVC风格的接口去调用远程接口。

对于Ribbon和Hystrix这些组件的搭配使用属于额外的扩展了,和Springcloud-Openfeign的基础改造无关,放到以后再分析。

2.2 改造内容

Springcloud最重要的改造内容有两点:

  1. 便于集成到Spring框架中;
  2. 支持像写SpringMVC接口一样编写调用远程的接口。

2.2.1 集成到Spring

原生Openfeign使用JDK动态代理来代理接口类的方式就决定了Feign接入Spring容器会非常简单,只需要把生成的动态代理对象交给Spring容器管理即可。大致流程图如下:

Feign集成到Spring流程

途中青色的是Spring刷新流程中解析@Configuration配置类的流程,红色的为Springcloud-Openfeign的可插拔引入实现流程,绿色的则是在注入bean时从FactoryBean获取实例的描述。

这一套实现方式对Spring的@Import实现原理和FactroyBean作用有一定了解的话应该比较容易理解Feign的Spring集成改造。在这里简单描述一下上面的流程:

  1. Spring解析@Configuration配置类的流程;
  2. 检测到@EnableFeignClients注解引入了FeignClientsRegistrar;
  3. FeignClientsRegistrar扫描指定目录下被@FeignClient注解的接口类;
  4. 将被扫描到的类使用FeignClientFactoryBean工厂类封装;
  5. 注入或需要使用Feign接口方法时,在工厂类里从Spring容器中取出需要替换的组件,并使用Builder构造器构造JDK动态代理类。

在FeignClientFactoryBean的getObject()方法中,代码的组成方式和构造原生Openfeign代理类的方式流程基本一致,只是构造组件改成了从Spring容器中获取。原生Openfeign的构造使用方式:

public interface TestFeign {
    /**
     * 测试方法
     */
    @RequestLine("GET /test.json")
    String test();
}

public void test() {
    TestFeign testFeign = Feign.builder()
            // .contract(new XXXContract()) 可替换
            // .encoder(new XXXEncoder()) 可替换
            // .decoder(new XXXDecoder()) 可替换
            .client(new OkHttpClient())
            .requestInterceptors(new ArrayList<>())
            .target(TestFeign.class, "localhost:8080");
    // 调用HTTP API像调用方法一样,调用路径为:GET localhost:8080/test.json
    System.out.println(testFeign.test());
}

FeignClientFactoryBean的getObject()方法流程和上述代码流程类似。

2.2.2 替换构造组件

再回顾一下原生Openfeign的几个核心组件:

  • Contract(协议):表示Feign支持的协议,一般而言指的是注解,通过替换不同的Contract以支持解析不同的注解。如果需要支持Spring的MVC注解,则需要替换该组件;
  • Client(客户端):Feign是简化HTTP调用的框架,本身不提供调用HTTP功能,依赖于客户端的具体实现类。如果要使用不同的HTTP工具,替换Client即可,Springcloud-Openfeign支持OkHttp3的Client实现;
  • Encoder(编码器):将传入的参数进行编码获得body、headers或文件流,负责把方法传入的对象转成对应的编码形式。最常见的是把@ReqeustBody转成json串放到body中;
  • Decoder(解码器):在获得响应的内容后,需要用解码器把响应内容转成接口方法返回类型的对象。如把常用的json返回串转成对应字段对象。

由上面一节已得知Spring可以使用FactoryBean来构造Feign的接口动态代理对象,如果要替换组件直接把需要替换的组件放入Spring容器中管理,并在构造时取出对应的组件把默认的组件一一替换,这样就可以达到替换原生Feign的核心组件以支持不同的功能了。示意图如下:

替换核心组件示意图
图中黑色框为原生Feign提供的接口,红色部分为官方默认实现类,绿色部分则是Spring的实现类,把绿色部分的实现类自动注入到Spring容器中,在FactoryBean构造时取出来进行替换,这样就完成了功能替换或扩展。

通过上面两步的优化改造,原生Openfeign就被集成到了Springcloud体系中,成为了Springcloud-Openfeign。

2.3 初步集成使用

接下来看下Springcloud-Openfeign集成原生Openfeign后的简单使用案例:

/** 主函数启动类 */
@EnableFeignClients(basePackages = "xx.xx")
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class);
    }
}
/** 被Feign注解的接口类 */
@FeignClient(name = "test", url = "localhost:8081/springcloud-test/")
public interface HttpTestFeign {
    /** 需要调用的接口路径,使用的是SpringMVC注解 */
    @GetMapping("/test/t")
    String test();
}
/** 使用的类 */
@Service
public class TestService{
    /** 注入Feign接口类,注入时会使用工厂类构造代理对象 */
    @Autowired
    private HttpTestFeign httpTestFeign;
    /** 调用方法 */
    public String feign() {
        return httpTestFeign.test();
    }
}

yml文件的属性这里就不贴上去了,因为通过这几个配置,我们已经可以正常使用Springcloud-Openfeign来调用远程HTTP API了。

2.4 支持的扩展点

Feign是非常灵活的RPC框架,支持的扩展点也非常多,但作为RPC框架,如果要融入到微服务体系中必须要考虑到的功能有三:

  1. 集成熔断限流;
  2. 流量负载均衡;
  3. 服务发现与注册。

先看Feign主要组件的调用流程:
主要组件调用流程

从主要组件调用流程可以大概分析一下需要支持上面的三个功能大概可以替换哪些组件:

  1. 熔断限流:熔断限流由于触发了,整个流程就可以直接终止,因此肯定适合在起点位置进行处理,这样才能保证熔断限流后不会走多余的流程,提高性能。基于这样的原因熔断限流一般都是替换InvocationHandler,能够从起点终止全流程,避免多余的性能损耗;
  2. 流量负载均衡:需要在发起HTTP请求时进行流量管控,选择性能较好的接收方进行发送。这个功能可以放在Target和Client组件实现,但如果要控制HTTP客户端的相关参数,就只能放到Client组件实现。事实上和Feign搭配使用的Ribbon就是放在Client实现,以便控制HTTP工具的参数;
  3. 服务发现与注册:需要根据生产者和消费者的标识来动态的匹配具体调用地址,以避免开发者频繁维护ip+port。有两种情况:如果只是为了获得调用地址,可以在Spring容器中根据占位符替换,或在Target中根据标识从服务发现注册框架中取;但如果是为了获取调用地址列表做负载均衡,则不推荐集成到Feign中,而应该集成到负载均衡框架中,因为只有负载均衡框架关心服务列表,Feign只需要调用负载均衡框架。事实上Feign的服务发现注册就是使用Ribbon和Eureka集成,由Eureka提供服务列表给Ribbon,Ribbon再根据负载均衡情况进行选择,与而Feign则只需要调用Ribbon即可。

扩展点暂时便分析到这里,为后续分析和Ribbon、Eureka或Sentinel的集成做个铺垫。

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

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

相关文章

实验一 进程管理与进程同步

实验一 进程管理与进程同步 实验目的&#xff1a; 了解进程管理的实现方法&#xff0c;理解和掌握处理进程同步问题的方法。 实验内容&#xff1a; 实现银行家算法、进程调度过程的模拟、读者-写者问题的写者优先算法。 实验步骤&#xff1a; 1.银行家算法流程图 &…

Springboot +Flowable,任务认领和回退(一)

一.简介 有的时候&#xff0c;一个任务节点会存在多个候选人&#xff0c;例如&#xff1a;张三提交一个任务&#xff0c;这个任务即可以由李四处理&#xff0c;又可以由王五处理&#xff0c;那么针对这种多个任务候选人的情况&#xff0c;该如何处理&#xff1f; 二.绘制流程…

Java线程池及其实现原理

线程池概述 线程池&#xff08;Thread Pool&#xff09;是一种基于池化思想管理线程的工具&#xff0c;经常出现在多线程服务器中&#xff0c;如MySQL。 线程过多会带来额外的开销&#xff0c;其中包括创建销毁线程的开销、调度线程的开销等等&#xff0c;同时也降低了计算机…

Spark任务提交流程

1. yarn-client Driver在任务提交的本地机器上运行&#xff0c;Driver启动后会和ResourceManager通讯&#xff0c;申请启动ApplicationMaster; 随后ResourceManager分配Container&#xff0c;在合适的NodeManager上启动ApplicationMaster&#xff0c;此时的ApplicationMaster的…

华为网络设备+WinRadius 实现用户统一管理设备

一、直接贴配置 ###配置VTY用户界面所支持的协议、验证方式 user-interface vty 0 4 protocol inbound telnet authentication-mode aaa quit ###配置RADIUS认证 ###&#xff08;1&#xff09;配置RADIUS服务器模板&#xff0c;指定服务器的IP地址与端口号、共享密钥 radius-s…

Supervisor离线安装(python3.7.8)

Background supervisor是用Python语言开发的一套通用的进程管理程序&#xff0c;可以将一个普通的命令行进程变为后台daemon&#xff0c;并监控进程状态&#xff0c;异常退出时可以自动拉起&#xff1b;可在大多数unix系统上使用&#xff0c;不能在windows上运行&#xff1b;目…

学Python常逛的10个网站

这里写目录标题 一、Python官方文档二、牛客网三、Github四、w3school五、Chatgpt六、kaggle七、realpython八、medium九、stackoverflow十、geeksforgeeks 一、Python官方文档 最全面的Python学习网站非官方文档莫属&#xff0c;它不仅提供了下载安装教程、基础语法教程、标准…

编写UDP版本的客户-服务器程序(echo server 和 echo client)

目录 前言概要 关于数据报流的关键方法签名 UDP协议传输案例 服务端&#xff08;接收端&#xff09; 服务端完整代码 客户端(发送端) 客户端完整代码 创作不易多多支持&#x1f636;‍&#x1f32b;️&#x1f618; 前言概要 我们首先来了解一下, 什么是网络编程. 网络编程…

认识系统总线

目录 一、总线的基本概念 1.总线的定义 二、总线的分类 1.片内总线 2.系统总线 2.1数据总线 2.2地址总线 2.3控制总线 3.通信总线(通信总线) 三、总线特性及性能指标 1.总线特征 2.性能标准 2.1总线的传输周期(总线周期) 2.2总线时钟周期 2.3总线的工作频率 2.4…

vim编辑器命令模式——撤销与时间旅行

Vi介绍 Vi 编辑器是所有 Unix 及 Linux 系统下标准的编辑器&#xff0c;类似于 windows 系统下的 notepad &#xff08;记事本&#xff09;编辑器&#xff0c;由于在 Unix 及 Linux 系统的任何版本&#xff0c;Vi 编辑器是完全相同的&#xff0c;因此可以在其他任何介绍 vi 的地…

小红书数据,如何在垂类赛道中脱颖而出!

导语 近年来&#xff0c;泛娱乐内容在小红书平台盛行&#xff0c;面临流量见顶的情况。这时候&#xff0c;垂类账号的优势就显现出来&#xff0c;不仅可以规避激烈的竞争&#xff0c;还能去获取更精准的流量。 作为一个经久不衰的创作方向&#xff0c;美食赛道分化出教程、测…

webpack plugin原理以及自定义plugin

通过插件我们可以拓展webpack&#xff0c;加入自定义的构建行为&#xff0c;使webpack可以执行更广泛的任务。 plugin工作原理&#xff1a; webpack工作就像是生产流水线&#xff0c;要通过一系列处理流程后才能将源文件转为输出结果&#xff0c;在不同阶段做不同的事&#x…

核磁机器学习 | 基于机器学习的fMRI分类

导读 本文通过提取最显著的特征&#xff0c;将大脑图像分类为正常和异常&#xff0c;并对大脑各种状态的磁共振成像(MRI)进行了研究。本文描述了一种基于小波变换的方法&#xff0c;首先对图像进行分解&#xff0c;然后使用各种特征选择算法从MRI图像中提取最显著的大脑特征。…

[Netty] 面试问题 1 (十八)

文章目录 1.Netty的特点2.Netty应用场景3. Netty核心组件4.Netty的线程模型5. EventloopGroup和EventLoop6.Netty 的零拷贝7.Netty 长连接和心跳机制8.Netty 服务端和客户端的启动过程9.Netty 的 Channel 和 EventLoop10.Netty 的 ChannelPipeline11.Netty 中的 ByteBuf12.Nett…

数据分析01——Anaconda安装/Anaconda中的pip换源/jupyter配置

0、前言&#xff1a; 数据分析三大模块知识&#xff1a;numpy&#xff08;数组计算&#xff09;、pandas&#xff08;基于numpy开发&#xff0c;用于数据清洗和数据分析&#xff09;、matplotlib&#xff08;实现数据可视化&#xff09; 1、Anaconda安装&#xff1a; 安装Ana…

Spring常见面试题总结(2023最新版)

文章目录 1、谈谈你对Spring的理解&#xff1f;1.1 发展历程1.2 Spirng的组成1.3 Spring的好处 2、Autowired和Resource的区别2.1 共同点&#xff1a;2.2 Autowired2.3 Resource2.3.1 Resource的装配顺序 3、Spring常用注解3.1、给容器中注入组件3.1.1 包扫描组件标注注解3.1.2…

Faster-RCNN跑自己的数据集(详细过程)FPN学习

1、下载b站 &#xff1a;霹雳吧啦Wz 的代码 github链接&#xff1a;https://github.com/WZMIAOMIAO/deep-learning-for-image-processing 对应视频链接&#xff1a;2-自定义DataSet_哔哩哔哩_bilibili 2、配置环境&#xff0c;安装相应的包。 或者如果有报错可以直接更新重新…

数据结构之栈的详解

文章目录 一.什么是栈二. 栈的使用2.1栈的基本操作2.2 栈的基本使用 三.栈的实现3.1 数组实现栈的方式3.2 链式栈的实现 四.栈的应用4.1 括号匹配4.2 逆波兰表达式求值什么是逆波兰表达式 4.3 出栈入栈次序匹配4.4 最小栈五.总结 一.什么是栈 栈是一种先入后出(FILO)的线性表数…

【刷题笔记】结构体内存对齐举例+统计回文

一、结构体内存对齐举例 题目&#xff1a; 下面存在两个结构体&#xff1a; struct One {double d;char c;int i; } struct Two {char c;double d;int i; } 在#pragma pack(4)和#pragma pack(8)的情况下&#xff0c;结构体的大小分别是&#xff1f; 分析&#xff1a; C/C中结构…

mysql8.0性能对比以及新特性

MySQL8.0 性能测试与新特性介绍 性能对比 测试内容 测试mysql5.7和mysql8.0 分别在读写、只读、只写模式&#xff08;&#xff08;oltp_read_write&#xff0c;oltp_read_only&#xff0c;oltp_write_only&#xff09;&#xff09;下不同并发时的性能&#xff08;tps&#x…