Feign远程调用的基本流程通俗易懂

news2024/11/29 2:58:59

1. OpenFeign的源码解析

关于OpenFeign的源码解析这位博主写的非常详细,可先阅读该博客【OpenFeign调用服务的核心原理解析】,本文对其内容做了概括整理,较于源码解析 通俗易懂。

2. Feign远程调用的基本流程图解

Feign远程调用,核心就是通过一系列的封装和处理,将以Java注解方式定义的远程调用API接口,最终转换成HTTP的请求形式,然后将HTTP请求的响应结果,解码成Java Bean,返回给调用者。

Feign远程调用的基本流程,简单可以分成两步:一是生成Feign的动态代理;二是Feign执行。如下图所示:
在这里插入图片描述

从上图可以看到,Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的Request请求。通过Feign以及Java的动态代理机制,可以不用通过HTTP框架去封装HTTP请求报文的方式,完成远程服务的HTTP调用。

3. 与FeignInvocationHandler相关的远程调用执行流程

Feign远程调用接口的JDK Proxy实例的InvokeHandler调用处理器有多种,导致Feign远程调用的执行流程稍微有点区别,但是远程调用执行流程的主要步骤基本是一致的。这里主要介绍与默认的调用处理器FeignInvocationHandler相关的远程调用执行流程。

在这里插入图片描述

结合下面ICardFeignClient的JDK Proxy远程动态代理实例的getCardInfoByUserId(@Param("id") String id)方法远程调用,介绍一下调用执行过程:

@RestController
@RequestMapping("/test")
public class TestController {
    
    @Autowired
    private ICardFeignClient cardFeignClient;

    /*** 
     * @description: feign过程分析实例 
     * @param:  
     * @return:  
     * @author name silk
     * @date: 2024/3/29 9:10
     */
    @GetMapping("/feign")
    public String testFeign(String userId) {
        String cardInfo = cardFeignClient.getCardInfoByUserId(userId);
        return cardInfo;
    }
}
@FeignClient(value = "card-service", path = "/card")
public interface ICardFeignClient {

    @PostMapping("/getCard")
    String getCardInfoByUserId(@Param("id") String id);
}

第1步:通过Spring IOC 容器实例,装配代理实例,然后进行远程调用。

  • Feign在启动时,会为加上了@FeignClient注解的所有远程接口(如本例的ICardFeignClient接口),创建一个本地JDK Proxy代理实例,并注册到Spring IOC容器。在这里,暂且将这个Proxy代理实例,叫做CardProxy。这个代理的创建过程可参考推荐博客【OpenFeign调用服务的核心原理解析】。

  • 然后,在本实例的TestController调用代码中,通过@Autowired注解,按照类型或者名称进行匹配,从Spring IOC容器找到CardProxy这个代理实例,并且装配给@Autowired注解所在的成员变量,本实例的成员变量的名称为cardFeignClient。

  • TestController在进行getCardInfoByUserId()远程调用时,直接通过cardFeignClient成员变量,调用JDK Proxy动态代理实例的getCardInfoByUserId()方法。

第2步:执行InvokeHandler调用处理器的invoke()方法

  • JDK Proxy动态代理实例的真正的方法调用过程,具体是通过InvokeHandler调用处理器完成的。所以这里的CardProxy代理实例,会调用到默认的FeignInvocationHandler调用处理器实例的invoke()方法。

  • 通过前面推荐博客中FeignInvocationHandler调用处理器的详细介绍,已经知道默认的调用处理器FeignInvocationHandler,内部保持了一个远程调用方法实例和方法处理器的一个Key-Value键值对Map映射。FeignInvocationHandler在其invoke()方法中,会根据Java反射的方法实例,在dispatch映射对象中,找到对应的MethodHandler方法处理器,然后由后者完成实际的HTTP请求和结果的处理。
    在这里插入图片描述

  • 所以在第2步中,FeignInvocationHandler会从自己的dispatch映射中,找到getCardInfoByUserId()方法所对应的MethodHandler方法处理器,然后调用其 invoke()方法。

第3步:执行MethodHandler方法处理器的invoke()方法

  • 通过前面推荐博客关于MethodHandler方法处理器的非常详细的介绍,已经知道,feign默认的方法处理器为SynchronousMethodHandler,其invoke()方法主要是通过内部成员feign客户端成员client,完成远程URL请求执行和获取远程结果。(首先通过SynchronousMethodHandler内部的client实例,实质为负责客户端负载均衡LoadBalancerFeignClient实例,首先查找到远程的server服务端;然后再由LoadBalancerFeignClient实例内部包装的feign.Client.Default内部类实例,去请求server端服务器,完成URL请求处理。)
    在这里插入图片描述
    在这里插入图片描述

  • #targetRequest()方法在创建Request对象前,先执行Feign的拦截器逻辑
    在这里插入图片描述

  • feign.Client客户端有多种类型,不同的类型完成URL请求处理的具体方式不同。

第4步:通过feign.Client客户端成员,完成远程URL请求执行和获取远程结果

  • 如果MethodHandler方法处理器实例中的client客户端,是默认的feign.Client.Default实现类性,则使用JDK自带的HttpURLConnnection类,完成远程 URL 请求执行和获取远程结果;如果MethodHandler方法处理器实例中的client客户端,是ApacheHttpClient客户端实现类性,则使用Apache httpclient开源组件,完成远程URL请求执行和获取远程结果。其他的还有如,OkHttpClient类:内部使用OkHttp3开源组件完成URL请求处理的feign.Client客户端实现类。LoadBalancerFeignClient类:内部使用Ribbon负载均衡技术完成URL请求处理的feign.Client 客户端实现类。
  • 还有一些特殊场景使用的feign.Client客户端实现类,也可以定制自己的feign.Client实现类。

在这里插入图片描述

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

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

相关文章

Linux中数据呈现输入输出重定向

1 理解输入输出 目前为止,你已经知道了两种脚本输出的方法: 在显示器屏幕上显示输出 将输出重定向到文件中 1.1 标准文件描述符 Linux系统将每个对象当作文件处理。这包括输入和输出进程。Linux用文件描述符(file descriptor)来标识每个文件对象。文…

【CANN训练营笔记】Atlas 200I DK A2体验手写数字识别模型训练推理

环境介绍 开发板:Huawei Atals 200I DK A2 内存:4G NPU:Ascend 310B4 CANN:7.0 准备环境 下载编译好的torch_npu wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/wanzutao/torch_npu-2.1.0rc1-cp39-cp39-linux_aarch…

sql之每日五题day01--多表联查/聚合函数

sql错题记录 含有聚合函数的不能用where升序排列order byleft join多表联查inner join不返回null三表联查 含有聚合函数的不能用where SQL19 分组过滤练习题 题目:现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营&#x…

算法复习:链表

链表定义 struct ListNode { int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {} }; 链表的遍历:ListNode phead; while(p!null) pp.next; 找到链表的尾结点:phead; while(p.next!null)pp.next; 链表节点的个数: phead…

windows上配置Redis主从加哨兵模式实现缓存高可用

一、哨兵模式 哨兵(sentinel)是Redis的高可用性(High Availability)的解决方案:由一个或多个sentinel实例组成sentinel集群可以监视一个或多个主服务器和多个从服务器。当主服务器进入下线状态时,sentinel可以将该主服务器下的某…

基于PHP的新闻管理系统(用户发布版)

有需要请加文章底部Q哦 可远程调试 基于PHP的新闻管理系统(用户发布版) 一 介绍 此新闻管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。本新闻管理系统采用用户发布新闻,管理员审核后展示模式。 技术栈&am…

编曲知识15:重复段落编写 尾奏编写 家庭工作室搭建 硬件设备使用常识

15 重复段落编写 尾奏编写 家庭工作室搭建 硬件设备使用常识小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_6602a586e4b0694cc051476b?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 重复段落设计 第二段落指代间奏过后的段落 第二…

docker环境中宿主机防火墙添加ssh无法生效的问题分析

背景 在部署了docker容器的环境中,要在防火墙开通22端口,即ssh服务,以便在终端可以正常登陆。使用firewall-cmd在docker区域添加了22端口,但是没有起作用。后再public区域添加22端口才起作用。为什么docker区域不起作用&#xff…

数据结构与算法 顺序栈的基本运算

一、实验内容 编写一个程序sqstack.cpp,实现顺序栈的各种基本运算,并在此基础上写一个程序exp6.cpp,实现以下功能 初始化栈s判断栈是否为空依次进栈元素a,b,c,d,e判断栈是否为空输出出栈序列判断栈是否为空释放栈 二、实验步骤 1、sqstack.cpp 2、ex…

windows-MySQL5.7安装

1.安装包下载 https://downloads.mysql.com/archives/community/(社区版下载链接) 选择Archives可以下载历史包,此处使用5.7.43 2.解压文件 解压文件到你指定安装的目录:解压完成后在mysql-5.7.43-winx64下新建文件my.ini和d…

python中的deque详解

文章目录 摘要示例1:基本使用示例2:使用maxlen限制队列长度示例3:使用deque实现滑动窗口算法示例 4: 使用 deque 实现旋转数组示例 5: 使用 deque 实现最大/最小栈示例 6: 使用 deque 实现广度优先搜索(BFS)摘要 deque(双端队列)是Python标准库collections模块中的一个…

从0配置React

在本地安装和配置React项目,您可以使用create-react-app这个官方推荐的脚手架工具。以下是安装React的步骤,包括安装Node.js、使用create-react-app创建React应用,以及启动开发服务器。 下载安装node.js运行以下命令,验证Node.js…

《操作系统导论》第16章读书笔记:分段

《操作系统导论》第16章读书笔记:分段 —— 杭州 2024-03-31 夜 文章目录 《操作系统导论》第16章读书笔记:分段0.前言1.分段:泛化的基址/界限2.我们引用哪个段?3.栈怎么办4.支持共享5.细粒度与粗粒度的分段、操作系统支持6.小结7…

从vrrp、bfd、keepalived到openflow多控制器--理论篇

vrrp 在一个网络中,通常会使用vrrp技术来实现网关的高可用。 vrrp,即Virtual Router Redundancy Protocol,虚拟路由冗余协议。 应用场景 典型的如下面这个例子: 当Router故障后,将会导致HostA-C都无法连接外部的I…

嵌入式linux学习之opencv交叉编译

1.下载opencv源码 OpenCV官方源码下载链接为https://opencv.org/releases/,选择3.4.16版本下载。放在ubuntu系统~/opencv文件夹中,解压缩,opencv文件夹中新建build和install文件夹用于存放编译文件和安装文件: 2. 安装编译工具…

springboot配置文件application.properties,application.yml/application.yaml

application.properties Springboot提供的一种属性配置方式:application.properties 初始时配置文件中只有一行语句。 启动时,比如tomcat的端口号默认8080,路径默认。如果我们要改变端口号及路径之类的可以在application.properties中配置。…

【C语言环境】Sublime中运行C语言时MinGW环境的安装

要知道,GCC 官网提供的 GCC 编译器是无法直接安装到 Windows 平台上的,如果我们想在 Windows 平台使用 GCC 编译器,可以安装 GCC 的移植版本。 目前适用于 Windows 平台、受欢迎的 GCC 移植版主要有 2 种,分别为 MinGW 和 Cygwin…

【算法竞赛进阶指南】0x11 栈

0x11 栈 基础应用 两个栈维护前面区间的最小元素 41. 包含min函数的栈 - AcWing题库 可以开个小根堆维护最小值,但是这样时间是logN的。如果只用一个变量来存,一旦出现了出栈操作就无从下手了。因此用一个线性结构来保存每个历史时刻的最小值。 开两个…

vue3封装Element分页

配置当前页 配置每页条数 页面改变、每页条数改变都触发回调 封装分页 Pagination.vue <template><el-paginationbackgroundv-bind"$attrs":page-sizes"pageSizes"v-model:current-page"page"v-model:page-size"pageSize":t…

常用字符串函数及模拟实现

1.strlen() 用法:求字符串长度 size_t strlen(const char *Str) 参数:字符串的起始地址,可以传地址也可以直接传一个字符串 返回值:字符串长度 模拟实现: 自己实现求字符串长度的函数(三种方法)-CSDN博客 2.strcpy() 用法:拷贝字符串 char* strcpy(char*_Destination,co…