当今是微服务横行的时代,各个微服务之间相互调用是一件再平常不过的时候。在采用HTTP协议进行通信的微服务中,我们自己可能去封装一个HttpClient工具类去进行服务间的调用,封装一个HttpClient工具,我们就需要考虑一下这些事情:

  • 我们在发送一个HTTP请求时,我们需要选择请求方式GET、POST、DELETE等,我们需要构建请求参数、构建请求头信息等,那么作为一个工具类我们是不是也要提供各种参数的灵活配置;
  • 因为采用restful API 风格的HTTP请求参数和返回数据都是字符串的格式,那我们是否需要考虑序列化和反序列化问题;
  • 当同一个服务部署到多台服务器的时候,我们是不是应该采用轮询或者随机的方式去选择服务器,这也就是我们常说的负载均衡。从另一方面来说我们的核心是解决服务间的调用,但是我们在设计一个通用HttpClient工具的时候是否也应该支持负载均衡,以及如何和负载均衡高度解耦。

为此,大名鼎鼎的Feign应时而生,我们在学习Feign的实现的时候,我们应该带着这些问题去学习Feign的实现原理。

一、什么是Feign

Feign 是声明式 Web 服务客户端,它使编写 Web 服务客户端更加容易 Feign 不做任何请求处理,通过处理注解相关信息生成 Request,并对调用返回的数据进行解码,从而实现简化HTTP API 的开发。当然你也可以直接使用 Apache HttpClient 来实现Web服务器客户端,但是 Feign 的目的是尽量的减少资源和代码来实现和 HTTP API 的连接。通过自定义的编码解码器以及错误处理,你可以编写任何基于文本的 HTTP API。

Spring Cloud -- OpenFeign 核心原理

如果要使用 Feign,需要创建一个接口并对其添加 Feign 相关注解,另外 Feign 还支持可插拔编码器和解码器,致力于打造一个轻量级 HTTP 客户端。

如果你想直接使用原生的Feign的话,你可以去参考Feign配置使用,下面就是Feign针对一个HTTP API的接口定义:

interface GitHub {
  // RequestLine注解声明请求方法和请求地址,可以允许有查询参数
  @RequestLine("GET /user/list")
  List<User> list();
}

目前由于Spring Cloud微服务的广泛使用,广大开发者更倾向于使用spring-cloud-starter-openfeign,Spring Cloud 添加了对 Spring MVC 注解的支持,在微服务中我们的接口定义有所变化:

@FeignClient(name="服务名",contextId="唯一标识")
interface GitHub {
  @GetMapping("/user/list")
  List<User> list();
}

二、Feign 和 Openfeign 的区别

Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由社区进行维护,更名为 Openfeign。

2.1 Starter OpenFeign

当然了,基于 SpringCloud 团队对 Netflix 的情有独钟,你出了这么好用的轻量级 HTTP 客户端,我这老大哥不得支持一下,所以就有了基于 Feign 封装的 Starter。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

这个包引入了如下依赖:

<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-openfeign-core</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-commons</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-core</artifactId>
      <version>10.4.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-slf4j</artifactId>
      <version>10.4.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-hystrix</artifactId>
      <version>10.4.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-java8</artifactId>
      <version>10.4.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-loadbalancer</artifactId>
      <version>2.2.0.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
View Code

相关文章: