原生OpenFeign相较于传统HTTP工具的优化和原理

news/2024/11/17 7:20:20/

文章目录

  • 1.HTTP工具使用流程及问题
    • 1.1 使用OkHttp3流程示例
    • 1.2 存在的两大问题
  • 2.OpenFeign的优化
  • 3.OpenFeign实现原理
    • 3.1 使用Feign构造动态代理对象
    • 3.2 Feign动态代理的实现原理

本篇介绍的是springcloud-openfeign的底层框架io.github.openfeign,重点不是框架如何使用,而是介绍Feign如何基于传统HTTP工具使用方式进行抽象改进,提升其灵活性,并简单介绍一下其抽象组件及主要组件的使用时机

1.HTTP工具使用流程及问题

1.1 使用OkHttp3流程示例

以常用的OkHttp3工具框架为例,其一个大致的流程如下:

HTTP大致流程

其流程从下面的Java调用代码示例也可以看出来:

public static String doHttpPostReturnAsString(String url, String paramJson, int timeout, List<Interceptor> interceptors) {// 1.初始化客户端// 2.设置超时时间OkHttpClient client = CLIENT.newBuilder().connectTimeout(timeout, TimeUnit.MILLISECONDS).readTimeout(timeout, TimeUnit.MILLISECONDS).writeTimeout(timeout, TimeUnit.MILLISECONDS).build();// 3.设置拦截器if (!CollectionUtils.isEmpty(interceptors)) {for (Interceptor interceptor : interceptors) {client = client.newBuilder().addInterceptor(interceptor).build();}}// 4.根据url构建Request对象RequestBody body = RequestBody.create(JSON, paramJson);Request request = new Request.Builder().url(url).post(body).build();// 5.调用并获取Response,提取信息后完成调用try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {String string = response.body().string();return string;} else {LOGGER.error("doHttpGet error:{}", response.code());}} catch (Exception e) {LOGGER.error("doHttpGet error:", e);}return null;
}

1.2 存在的两大问题

这只是一个非常简单的实例,把调用方法写成工具类中的静态方法,就形成了一个可复用的静态工具类。其优点就是快速且较为简单维护,但最大缺点有二:

  1. 硬编码实现:如果要支持动态参数就会导致入参臃肿,不便于扩展;
  2. 现在的项目大部分都是用Spring管理对象的,静态工具类的方式也不便于将其纳入到Spring中进行管理,和Spring中大部分的框架没办法优雅的集成。

2.OpenFeign的优化

针对上面说的第一个硬编码实现问题,解决它就需要让每个功能模块分工明确,可替换性强,这样才可以做到不同场景使用不同组件实现以不同功能,避免硬编码问题。而Feign的做法便是使用了这种思路,针对HTTP工具的不同流程,抽象出了对应的组件,每个组件提供默认的实现,如果要针对某一流程实现特殊的逻辑,则替换对应的实现组件。

先看个使用Feign的简单示例:

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.jsonSystem.out.println(testFeign.test());
}

OpenFeign的调用流程相较于静态工具类变成了两步:

  1. 先使用Feign构造实例化一个接口代理对象;
  2. 调用接口对象的对应方法完成HTTP API的调用。

OpenFeign使用了大量组件来避免硬编码问题,向开发者屏蔽了操作HTTP工具的API操作。在传统的HTTP调用流程中Openfeign引入了如下变化:

Openfeign引入主要组件图

从图中可以看到引入的组件非常多,针对HTTP工具执行一系列操作时引入了相应的组件,但关键核心的组件一共就5个:

  1. Contract(协议):表示Feign支持的协议,一般而言指的是注解,通过替换不同的Contract以支持解析不同的注解。如果需要支持Spring的MVC注解,则需要替换该组件;
  2. Client(客户端):Feign是简化HTTP调用的框架,本身不提供调用HTTP功能,依赖于客户端的具体实现类。如果要使用不同的HTTP工具,替换Client即可;
  3. RequestTemplate(请求模板):接口方法在编写后,其参数注解等信息基本不会再改动,而请求模板保存的就是实例化时解析注解的信息。如请求头信息、参数对应填充位置等,保证后续填充数据时可直接获取对应位置的对象数据;
  4. Encoder(编码器):将传入的参数进行编码获得body、headers或文件流,负责把方法传入的对象转成对应的编码形式。最常见的是把@ReqeustBody转成json串放到body中;
  5. Decoder(解码器):在获得响应的内容后,需要用解码器把响应内容转成接口方法返回类型的对象。如把常用的json返回串转成对应字段对象。

理解了Feign抽象出这些组件的初衷,就可以很容易理解Feign各个组件的作用了。

3.OpenFeign实现原理

由上节可知,OpenFeign的实现原理分为了两个大的步骤:

  1. 使用Feign构造获得JDK动态代理对象;
  2. 调用动态代理对象的方法执行代理逻辑,并填入请求参数及解析响应数据。

接下来以这两个步骤分别分析一下OpenFeign的实现原理。

3.1 使用Feign构造动态代理对象

相较于原来的静态工具类,这个步骤是多出来的,Feign这样的做法是为了让相同的调用场景下构造出来的对象可以重复使用,提升使用效率。

构造动态代理对象流程

根据上面的流程构造出来的代理对象可以反复使用,一次构造解析,终身使用。因此在使用Spring等容器框架时,通常会把构造出来的代理对象以单例形式放入到容器中,以便使用时直接获取。如下代码:

@Configuration
public class FeignConfiguration {@Beanpublic TestFeign testFeign() {return Feign.builder()// .contract(new XXXContract()) 可替换// .encoder(new XXXEncoder()) 可替换// .decoder(new XXXDecoder()) 可替换.client(new OkHttpClient()).requestInterceptors(new ArrayList<>()).target(TestFeign.class, "localhost:8080");}
}// 使用时
@Autowired
private TestFeign testFeign;

3.2 Feign动态代理的实现原理

获得构造出来的JDK动态代理对象后,调用接口方法将会触发Feign的动态代理逻辑,帮我们完成HTTP API的调用。

动态代理填充参数完成请求

图中只写了主流程中比较重要的部分组件及组件在流程中的执行时间,只要知道了不同的组件在Feign工作流程中的生效时机,就可以自定义实现组件替换默认的组件,实现功能的扩展。

Feign解决与容器框架的集成问题便是基于上面两点实现的,把HTTP API写到一个个的接口中,使用JDK动态代理对接口方法完成代理,这样便可以把接口交给容器框架管理,需要使用时把代理对象取出来调用对应的方法即可。

如果框架便于集成,且扩展性很强,那么使用场景便可以得到扩充,如Springcloud便将Feign的组件进行替换,实现了Springcloud-openfeign框架,这也是Feign关键功能抽象组件带来的好处。


http://www.ppmy.cn/news/59153.html

相关文章

介绍一款优秀的网址导航,可以部署到自己公司内部:hexo-theme-webstack

GitHub - HCLonely/hexo-theme-webstack: A hexo theme based on webstack. | 一个基于webstack的hexo主题。 中文文档 A Hexo theme based on WebStackPage. Installation hexo > 4.0 git clone https://github.com/HCLonely/hexo-theme-webstack themes/webstack hexo …

E. Train Hard, Win Easy(数学推导 + 前缀和)

Problem - E - Codeforces 这是一个有关竞赛编程的问题。Zibi 是一名竞赛编程教练&#xff0c;有 n 名选手想要备战。培训比赛具有一些不同寻常的规则——每个团队有两名成员和两个问题&#xff0c;每个选手都会编写其中一个问题的代码。当然&#xff0c;一个团队中的人将编写不…

感知机介绍

1&#xff0c;数学定义&#xff1a; Note:<>在数学中通常指求期望的意思。 假设我们用感知机区分cat和dog&#xff0c;使用下面三个特征&#xff1a;x1: color of hair&#xff1b;x2:length of leg&#xff1b;x3:volume of head。cat 用1表示&#xff0c;dog用-1表示&…

MySQL数据备份和恢复

MySQL数据备份和恢复 数据备份 mysqldump是MySQL数据库备份工具&#xff0c;可以备份MySQL数据库中的数据和结构&#xff0c;生成.sql文件&#xff0c;方便数据的迁移和恢复。 使用mysqldump工具前一定要配置环境变量 打开开始菜单&#xff0c;搜索“环境变量”。点击“编辑…

聚观早报|五一假期机票均价超1200元;苹果自动驾驶测试减员超25%

今日要闻&#xff1a;五一假期国内机票均价超1200元&#xff1b;谷歌、微软、OpenAI等将讨论AI问题&#xff1b;苹果自动驾驶测试司机团队减员超25%&#xff1b;“五一”最热十大景区出炉&#xff1b;李想辟谣理想汽车砸钱雇媒体营销 五一假期国内机票均价超1200元 5 月 3 日…

【Linux内核解析-linux-5.14.10-内核源码注释】MM内存管理内核启动初始化源码解析

源码 这是Linux内核中的mm_init函数的代码&#xff0c;其作用是初始化内存管理相关的组件和数据结构。 static: 这是一个函数声明修饰符&#xff0c;表示该函数只在当前文件中可见。 void __init: 这是函数的返回类型和修饰符&#xff0c;表示该函数是内核初始化代码。 page…

恒源云使用

目录 一、OSS的使用 1、oss本地上传到服务器 2、oss服务器登录下载到服务器 3、oss服务器上下载到本地 二、解压缩 三、训练 四、训练结束自动关机、上传数据 五、查看实例储存空间 六、文件管理 七、所需的库 八、网盘数据上传下载 1&#xff09;下载命令工具 2…

明明花钱上了ERP,为什么还要我装个MES系统

目前&#xff0c; ERP系统依旧是很多制造企业的选择。据统计&#xff0c;ERP系统的应用已经达到70&#xff05;以上&#xff0c;但是在车间的应用&#xff0c; MES系统的应用比例并不高。那么&#xff0c;为什么现在很多企业又都选择再上个MES呢&#xff1f; MES系统是一个面向…