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

news2024/11/20 3:23:15

文章目录

  • 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.json
    System.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 {
    @Bean
    public 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.coloradmin.cn/o/491952.html

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

相关文章

【Redis】Redis缓存雪崩、缓存穿透、缓存击穿(热key问题)

目录 一、缓存穿透 1、概念 2、解决办法 1.缓存空对象 2.布隆过滤 二、缓存雪崩 1、概念 2、解决办法 1.给key设置随机的过期时间TTL 2.业务添加多级缓存 3.利用集群提供服务可用性 4.缓存业务添加降级限流 三、缓存击穿 1、概念 2、解决办法 1.互斥锁 2.逻辑…

数据结构:第三章 栈、队列和数组

文章目录 一、栈1.1栈的概念1.1.1栈的定义1.1.2栈的基本操作1.1.3栈的常见考题1.1.4小结 1.2栈的顺序存储实现1.2.1顺序栈的定义1.2.2初始化操作1.2.3进栈操作1.2.4出栈操作1.2.5获取栈顶元素操作1.2.6共享栈1.2.7小结 1.3栈的链式存储实现1.3.1链栈的定义1.3.2小结 二、队列2.…

Optional的使用详解

工作中经常会调外部接口、或者查询表等&#xff0c;如果对返回结果不进行空指针判断的话就会导致空指针异常。针对这种情况经常会使用if进行判断: private boolean isNotNull(Object param) {if (param null) {return false;} else {return true;}}这样写其实功能上没有任何问…

上班摸鱼在群里吹牛B,逮到一个阿里10年老测试开发,聊过之后收益良多...

老话说的好&#xff0c;这人呐&#xff0c;一单在某个领域鲜有敌手了&#xff0c;就会闲得蛋疼。前几天我在上班摸鱼刷群的时候认识了一位阿里测试开发大佬&#xff0c;在华为工作了10年&#xff0c;因为本人天赋比较高&#xff0c;平时工作也兢兢业业&#xff0c;现在企业内有…

USB协议分析仪

1 ULPI PHY passive sniffing mode 概念: non driving, no pull-up, no pull-down Function Control.opMode 1; // non-Driving OTG Control.DpPulldown 0; // no pull-down OTG Control.DmPulldown 0; // no pull-down USB IO.ChargerPullupEnDP 0; // no pull-up USB IO.…

九、MyBatis动态SQL

文章目录 九、动态SQL9.1 if9.2 where9.3 trim9.4 choose、when、otherwise9.5 foreach9.6 SQL片段 本人其他相关文章链接 九、动态SQL 9.1 if 总结&#xff1a;根据标签中test属性所对应的表达式决定标签中的内容是否需要拼接到SQL中。 User getUserByParamsWithIf(User user…

缓存击穿,穿透,雪崩

一、缓存穿透 是用户访问的数据既不在缓存当中&#xff0c;也不在数据库中。 如果从数据库查询不到数据&#xff0c;则不写入缓存。这就导致每次请求都会到数据库进行查询&#xff0c;缓存也失去了意义。 当高并发或有人利用不存在的Key频繁攻击时&#xff0c;数据库的压力骤…

AI 工具合辑盘点(四)持续更新

AI 视频生成和编辑工具 当今&#xff0c;视频已经成为最受欢迎的媒介之一。我们喜欢观看视频&#xff0c;但是制作高质量的视频需要耗费大量时间和精力。 无论你是内容创作者、专业视频编辑师&#xff0c;还是完全的新手&#xff0c;按照传统方式制作视频需要掌握各种知识、技…

【Maxwell】MySQL数据监听

背景 我们都知道随着业务的发展,监听数据库的数据变更及时性是必须的,虽然我们可以在入库之前进行处理,但是有个问题就是事务的一致性不好掌控,而且很多业务都是微服务的,那么不在一个微服务中,可能有需要跨服务去调用,那么此时直接去监听mysql的binlog来实现数据的操作…

这一篇Databinding应该可以帮助迅速上手吧

Databinding使用篇&#xff08;迅速上手&#xff09; 使用前需要在模块级别的build.gradle里面的android闭包里添加&#xff1a; dataBinding{enabled true}接着在layout文件中按下Alt 回车&#xff0c; 将布局转换成data binding layout即可&#xff0c;此时编译就会生成对…

【JAVAEE】创建线程的方式及线程的常用方法

目录 1.创建线程的四种方式 1.1继承Thread类 1.2实现Runnable接口 1.3匿名内部类 1.4lambda表达式 2.多线程的优势-增加运行速度 3.Thread类及常用方法 3.1构造方法 3.2常见属性 演示后台线程 演示线程是否存活 3.3线程中断 3.4线程等待-join() 3.5获取当前线程 …

23年5月高项备考学习笔记——信息系统管理

管理&#xff1a;监督系统的设计和结构 系统&#xff1a;提供蓝图 系统管理&#xff1a; 规划和组织&#xff1a;业务战略、组织机制、信息系统 业务战略&#xff1a; 总成本领先战略 差异性战略 专注化战略 设计和实施&#xff1a;战略转成需求&#xff0c;便管理&#xff1b…

5月5号软件资讯更新合集.....

Visual Studio Code 1.78 发布 VS Code 1.78 已发布&#xff0c;此版本一些主要亮点包括&#xff1a; 辅助功能改进 - 更好的屏幕阅读器支持、新的音频提示。 新的颜色主题 - “Modern” 浅色和深色主题默认设置。 配置文件模板 - Python、Java、数据科学等的内置模板。 新…

2023年6月DAMA-CDGA/CDGP数据治理认证报名请尽早啦!

6月18日DAMA-CDGA/CDGP数据治理认证考试开放报名中&#xff01; 考试开放地区&#xff1a;北京、上海、广州、深圳、长沙、呼和浩特、杭州、南京、济南、成都、西安。其他地区凑人数中… DAMA-CDGA/CDGP数据治理认证开班时间&#xff1a;5月7日 DAMA认证为数据管理专业人士提供…

线上FullGC问题排查实践——手把手教你排查线上问题 | 京东云技术团队

作者&#xff1a;京东科技 韩国凯 一、问题发现与排查 1.1 找到问题原因 问题起因是我们收到了jdos的容器CPU告警&#xff0c;CPU使用率已经达到104% 观察该机器日志发现&#xff0c;此时有很多线程在执行跑批任务。正常来说&#xff0c;跑批任务是低CPU高内存型&#xff0c…

【马蹄集】第九周作业

第九周作业 目录 MT2125 一样的虫子MT2126 AB数对MT2127 权值计算MT2128 黑客小码哥MT2129 来给单词分类 MT2125 一样的虫子 难度&#xff1a;黄金    时间限制&#xff1a;1秒    占用内存&#xff1a;128M 题目描述 有 N 只虫子&#xff0c;每只虫子有6条腿&#xff0c;每…

通过Python的pytesseract库识别图片中的文字

文章目录 前言一、pytesseract1.pytesseract是什么&#xff1f;2.安装pytesseract3.查看pytesseract版本4.安装PIL5.查看PIL版本 二、Tesseract OCR1.Tesseract OCR是什么&#xff1f;2.安装Tesseract OCR3.安装 Tesseract OCR 语言包 三、使用方法1.引入库2.打开图片文件3.使用…

聊一聊 Valgrind 监视非托管内存泄露和崩溃

一&#xff1a;背景 1. 讲故事 只要是程序总会出现各种莫名其妙的问题&#xff0c;比如&#xff1a;非托管内存泄露&#xff0c;程序崩溃&#xff0c;在 Windows 平台上一般用微软自家的官方工具 App Verifier 就可以洞察&#xff0c;那问题出在 Linux 上怎么办呢&#xff1f…

块状链表实现BigString大字符串操作(golang)

前言 块状链表是介于链表和数组之间的数据结构&#xff0c;能够在 O ( n ) O(\sqrt{n}) O(n ​)时间内完成插入、删除、访问操作。 数据结构如图所示。假设最大容量为 n n n, 则它有一个长度为 s n s\sqrt{n} sn ​的链表。链表中每个结点是一个长度为 2 n 2 \times \sqrt{…

C#_各类应用程序

目录 前言 1. 第一个程序&#xff1a;Hello&#xff0c;World&#xff01; 1.1 Console 1.2 Windows Forms 1.3 WPF&#xff08;Windows Presentation Foundation&#xff09; 1.4 ASP.NET Web Forms 1.5 ASP.NET MVC(Model - View - Controller) 1.6 Windows Store A…