聊聊 Feign 的实现原理

Feign是一个基于接口和注解的HTTP客户端,简化了HTTP请求的调用。它封装了HTTP请求调用流程,使得在微服务中调用HTTP服务更加简单。本文介绍了Feign的基本概念、为何使用Feign,以及通过示例展示了如何原生和结合Spring Cloud使用Feign。在内部,Feign通过动态代理生成接口实现,调用时通过FeignInvocationHandler处理HTTP请求,实现了请求的发送和响应的解码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

What is Feign

Feign 是⼀个 HTTP 请求的轻量级客户端框架。通过 接口 + 注解的方式发起 HTTP 请求调用,面向接口编程,而不是像 Java 中通过封装 HTTP 请求报文的方式直接调用。服务消费方拿到服务提供方的接⼝,然后像调⽤本地接⼝⽅法⼀样去调⽤,实际发出的是远程的请求。让我们更加便捷和优雅的去调⽤基于 HTTP 的 API,被⼴泛应⽤在 Spring Cloud 的解决⽅案中。开源项目地址: Feign ,官方描述如下:

Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign’s first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.

Why Feign

Feign 的首要目标就是减少 HTTP 调用的复杂性。在微服务调用的场景中,我们调用很多时候都是基于 HTTP 协议的服务,如果服务调用只使用提供 HTTP 调用服务的 HTTP Client 框架(e.g. Apache HttpComponnets、HttpURLConnection OkHttp 等),我们需要关注哪些问题呢?

相比这些 HTTP 请求框架,Feign 封装了 HTTP 请求调用的流程,而且会强制使用者去养成面向接口编程的习惯(因为 Feign 本身就是要面向接口)。

Demo

原生使用方式

以获取 Feign 的 GitHub 开源项目的 Contributors 为例,原生方式使用 Feign 步骤有如下三步(这里以使用 Gradle 进行依赖管理的项目为例): 第一步: 引入相关依赖:implementation ‘io.github.openfeign:feign-core:11.0’ 在项目的 build.gradle 文件的依赖声明处 dependencies 添加该依赖声明即可。

第二步:声明 HTTP 请求接口 使用 Java 的接口和 Feign 的原生注解 @RequestLine 声明 HTTP 请求接口,从这里就可以看到 Feign 给使用者封装了 HTTP 的调用细节,极大的减少了 HTTP 调用的复杂性,只要定义接口即可。

第三步:配置初始化 Feign 客户端 最后一步配置初始化客户端,这一步主要是设置请求地址、编码(Encoder)、解码(Decoder)等。

通过定义接口,使用注解的方式描述接口的信息,就可以发起接口调用。最后请求结果如下:

结合 Spring Cloud 使用方式

同样还是以获取 Feign 的 GitHub 开源项目的 Contributors 为例,结合 Spring Cloud 的使用方式有如下三步: 第一步: 引入相关 starter 依赖:org.springframework.cloud:spring-cloud-starter-openfeign 在项目的 build.gradle 文件的依赖声明处 dependencies 添加该依赖声明即可。

第二步:在项目的启动类 XXXApplication 上添加 @EnableFeignClients 注解启用 Feign 客户端功能。

第三步:创建 HTTP 调用接口,并添加声明 @FeignClient 注解。 最后一步配置初始化客户端,这一步主要是设置请求地址(url)、编码(Encoder)、解码(Decoder)等,与原生使用方式不同的是,现在我们是通过 @FeignClient 注解配置的 Feign 客户端属性,同时请求的 URL 也是使用的 Spring MVC 提供的注解。

### Ribbon 和 Feign 组合使用原理解析 #### 一、Ribbon 的工作机制 Ribbon 是 Netflix 开源的一款客户端负载均衡器,能够帮助应用程序轻松实现对 HTTP 和 TCP 客户端行为的控制。当应用启动时,Ribbon 初始化并加载一系列配置项,这些配置决定了如何选取目标服务器来发起远程调用。 对于微服务架构而言,Ribbon 可以与 Eureka 或 Nacos 这样的服务注册中心协同工作,动态获取最新的服务实例列表[^1]。每当需要向某个特定的服务发送请求之前,Ribbon 就会在已知的服务实例集合上执行预设好的负载平衡逻辑——比如简单的轮询方式或是更复杂的基于权重的选择方法——从而决定最终应该联系哪个具体的节点完成此次交互操作。 #### 二、Feign 的功能概述 Feign 则是一个声明式的 Web Service Client,它使得编写 HTTP API 请求变得非常简单直观。开发者只需要定义接口及其上的注解即可描述对外部 RESTful 接口的访问需求;而无需关心底层连接细节以及序列化过程等问题。Spring Cloud 对其进行了增强支持,在此基础上实现了自动装配等功能特性[^4]。 #### 三、两者结合后的运作流程 当 Ribbon 和 Feign 同时存在于项目依赖当中时: - 应用程序通过 Feign 创建用于表示待调用远端资源的方法签名; - 在实际运行期间,每一次触发由上述接口所代表的操作前,都会先经过 Ribbon 处理阶段; - 此刻 Ribbon 根据既定规则挑选出最合适的一个候选者作为本次通信的目的地,并将其 IP 地址连同端口号一同返回给 Feign 层面; - 随后 Feign 构建完整的 URL 并发出真正的网络请求至选定的服务实例上去执行具体业务逻辑[^2]。 这种集成模式不仅简化了开发人员的工作量,同时也增强了系统的灵活性和可扩展性,因为所有的选路决策都交给了独立于业务代码之外的专业组件去处理。 ```java // 示例:定义一个 FeignClient 来消费其他微服务API @FeignClient(name="example-service", fallback=ExampleServiceFallback.class) public interface ExampleServiceApi { @RequestMapping(method = RequestMethod.GET, value = "/api/example") String getExample(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值