万字长文 | 深入理解 OpenFeign 的架构原理

上次我们深入讲解了Ribbon 的架构原理,这次我们再来看下 Feign 远程调用的架构原理。

万字长文 | 深入理解 OpenFeign 的架构原理_第1张图片

一、理解远程调用

远程调用怎么理解呢?

远程调用 和 本地调用 是相对的,那我们先说本地调用更好理解些,本地调用就是同一个 Service 里面的方法 A 调用方法 B。

那远程调用就是不同 Service 之间的方法调用。Service 级的方法调用,就是我们自己构造请求 URL和请求参数,就可以发起远程调用了。

在服务之间调用的话,我们都是基于 HTTP 协议,一般用到的远程服务框架有 OKHttp3,Netty, HttpURLConnection 等。其调用流程如下:

万字长文 | 深入理解 OpenFeign 的架构原理_第2张图片

但是这种虚线方框中的构造请求的过程是很 繁琐 的,有没有更 简便 的方式呢?

Feign 就是来简化我们发起远程调用的代码的,那简化到什么程度呢? 简化成就像调用本地方法那样简单。

比如我的开源项目 PassJava 中的使用 Feign 执行远程调用的代码:

//远程调用拿到该用户的学习时长
R memberStudyTimeList = studyTimeFeignService.getMemberStudyTimeListTest(id);

而 Feign 又是 Spring Cloud 微服务技术栈中非常重要的一个组件,如果让你来设计这个微服务组件,你会怎么来设计呢?

我们需要考虑这几个因素 :

  • 如何使远程调用像本地方法调用简单?

  • Feign 如何找到远程服务的地址的?

  • Feign 是如何进行负载均衡的?

接下来我们围绕这些核心问题来一起看下 Feign 的设计原理。

二、Feign 和 OpenFeign

OpenFeign 组件的前身是 Netflix Feign 项目,它最早是作为 Netflix OSS 项目的一部分,由 Netflix 公司开发。后来 Feign 项目被贡献给了开源组织,于是才有了我们今天使用的 Spring Cloud OpenFeign 组件。

Feign 和 OpenFeign 有很多大同小异之处,不同的是 OpenFeign 支持 MVC 注解。

可以认为 OpenFeign 为 Feign 的增强版 。

简单总结下 OpenFeign 能用来做什么:

  • OpenFeign 是声明式的 HTTP 客户端,让远程调用更简单。

  • 提供了HTTP请求的模板,编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息

  • 整合了Ribbon(负载均衡组件)和 Hystix(服务熔断组件),不需要显示使用这两个组件

  • Spring Cloud Feign 在 Netflix Feign的基础上扩展了对SpringMVC注解的支持

三、OpenFeign 如何用?

OpenFeign 的使用也很简单,这里还是用我的开源 SpringCloud 项目 PassJava 作为示例。

开源地址: https://github.com/Jackson0714/PassJava-Platform

喜欢的小伙伴来点个 Star 吧,冲 2K Star。

Member 服务远程调用 Study 服务的方法 memberStudyTime(),如下图所示。

万字长文 | 深入理解 OpenFeign 的架构原理_第3张图片

第一步 :Member 服务需要定义一个 OpenFeign 接口:

@FeignClient("passjava-study")
public interface StudyTimeFeignService {
    @RequestMapping("study/studytime/member/list/test/{id}")
    public R getMemberStudyTimeListTest(@PathVariable("id") Long id);
}

我们可以看到这个 interface 上添加了注解 @FeignClient ,而且括号里面指定了服务名:passjava-study。 显示声明 这个接口用来远程调用 passjava-study 服务。

第二步 :Member 启动类上添加 @EnableFeignClients 注解开启远程调用服务,且需要开启服务发现。如下所示:

@EnableFeignClients(basePackages = "com.jackson0714.passjava.member.feign")
@EnableDiscoveryClient

第三步 :Study 服务定义一个方法,其方法路径和 Member 服务中的接口 URL 地址一致即可。

URL 地址:"study/studytime/member/list/test/{id}"

@RestController
@RequestMapping("study/studytime")
public class StudyTimeController {
    @RequestMapping("/member/list/test/{id}")
    public R memberStudyTimeTest(@PathVariable("id

你可能感兴趣的:(程序员,计算机,Java,架构,java,开发语言)