Appearance
OpenFeign 简介
1. 概述
近期在工作中,有一个 HTTP 请求外部系统的需求,当时脑海中首先想到的就是使用 OkHttp3 框架,封装一个 HTTP 请求工具类;但是偶然间发现,使用 OpenFeign 不仅可以实现调用微服务,也可以指定 url 进行 HTTP 请求,相比之前,OpenFeign 使用更简单,开发更简单明了;所以,现在就对 OpenFeign 进行全面的学习下。
2. OpenFeign 介绍
OpenFeign 是一个显示声明式的 WebService 客户端。使用 OpenFeign 能让编写 Web Service 客户端更加简单。使用时只需定义服务接口,然后在上面添加注解。OpenFeign 也支持可拔插式的编码和解码器。Spring Cloud 对 Feign 进行了封装,使其支持 MVC 注解和 HttpMessageConverts。和 Eureka(服务注册中心)、Ribbon 组合可以实现负载均衡。在 Spring Cloud 中使用 OpenFeign,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问 HTTP 请求,非常的方便。
OpenFeign 的设计宗旨式简化 Java Http 客户端的开发。Feign 在 RestTemplate 的基础上做了进一步的封装,由其来帮助我们定义和实现依赖服务接口的定义。在 OpenFeign 的协助下,我们只需创建一个接口并使用注解的方式进行配置(类似于 Dao 接口上面的 Mapper 注解)即可完成对服务提供方的接口绑定,大大简化了 Spring cloud Ribbon 的开发,自动封装服务调用客户端的开发量。
OpenFeign 集成了 Ribbon,利用 ribbon 维护了服务列表,并且通过 ribbon 实现了客户端的负载均衡。与 ribbon 不同的是,通过 OpenFeign 只需要定义服务绑定接口且以申明式的方法,优雅而简单的实现了服务调用。
3. 基础使用
- pom.xml 引用
xml
<!--Open feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 启用 OpenFeign,在启动类上增加
@EnableFeignClients
注解
java
@SpringBootApplication
@EnableFeignClients
public class OpenFeignMain {
public static void main(String[] args) {
SpringApplication.run(OpenFeignMain.class, args);
}
}
- 编写接口,即远程服务调用的接口
java
@Component
//添加 @FeignClient 注解即可绑定服务提供者
@FeignClient(value = "test-service")
public interface TestService {
@GetMapping("/test/user/list")
ResultDto list();
}
@FeignClient(value = "test-service")
中的test-service
即调用的微服务在注册中心注册的名称
@GetMapping
即调用的服务的URL地址,使用 POST 方式调用,也支持 POST 等方式
- 调用
java
@RestController
@RequestMapping("/consumer")
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/list")
public ResultDto list() {
return testService.list();
}
}
4. 参数配置
4.1 超时控制
OpenFeign 默认超时时间为 1s,超过 1s 就会返回错误页面。如果我们的接口处理业务确实超过 1s,就需要对接口进行超时配置,如下:
yml
#设置feign客户端连接所用的超时时间,适用于网络状况正常情况下,两端连接所用时间
ribbon:
#指的是建立连接所用时间
ReadTimeout: 1000
#指建立连接后从服务读取到可用资源所用时间
ConnectTimeout: 1000
4.2 日志增量
通过指定 feign.Logger
的日志级别参数来控制日志输出:
java
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenFeignConfig {
@Bean
Logger.Level feignLogLevel() {
return Logger.Level.FULL;
}
}
日志级别有以下几种:
NONE
:默认,不显示任何日志;
BASIC
: 仅记录请求方法、URL、响应状态码及执行时间;
HEADERS
:除了 BASIC 中定义的信息之外,还有请求头和响应头信息;
FULL
:除了 HEADERS 中定义的信息之外,还有请求的正文和响应数据。
以上是通过代码的形式进行配置,也可以直接通过配置文件的方式指定日志级别,如下所示:
yml
logging:
level:
com.demo.feign.TestService: DEBUG
feign:
# Feign 客户端配置,对应 FeignClientProperties 配置属性类
client:
# config 配置项是 Map 类型。key 为 Feign 客户端的名字,value 为 FeignClientConfiguration 对象
config:
# 全局级别配置
default:
logger-level: BASIC
# 客户端级别配置
demo-provider:
logger-level: FULL
5. 单独使用
在使用 Spring Cloud 的项目中,我们大多数是通过 Feign 调用从 Ribbon 负载均衡选择的服务实例,而 Ribbon 是通过注册中心获取到的服务实例列表。但是有些场景下,可能想要单独使用 Feign 调用,比如调用第三方服务,或者调用的虽然是内部服务,但是并没有注册到注册中心。这个时候就需要直接指定服务的 IP 地址等信息,进行直接的调用。
java
//@FeignClient(name = "demo-provider")
@FeignClient(name = "iocoder", url = "http://www.iocoder.cn")
public interface DemoProviderFeignClient {
//@GetMapping("/echo")
//String echo(@RequestParam("name") String name);
@GetMapping("/")
String echo(@RequestParam("name") String name);
}
将 @FeignClient
注解的 url
属性设置要调用的服务的地址即可。
6. HTTP 客户端
默认情况下,Feign 通过 JDK 自带的 HttpURLConnection 封装了 Client.Default,实现 HTTP 调用的客户端。因为 HttpURLConnection 缺少对 HTTP 连接池的支持,性能较低,因此 Feign 提供了另外两个 HTTP 客户端:
ApacheHttpClient,基于 Apache HttpClient 封装
OkHttpClient,基于 OkHttp 封装
6.1 使用 Apache HttpClient
- 引入
feign-httpclient
依赖
xml
<!-- 引入 Feign Apache HttpClient 依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
- 修改配置
yml
feign:
# Feign Apache HttpClient 配置项,对应 FeignHttpClientProperties 配置属性类
httpclient:
#是否开启,默认为 true
enabled: true
#最大连接数,默认为 200
max-connections: 200
#每个路由的最大连接数,默认为 50
max-connections-per-route: 50
虽然说 feign.httpclient.enable
默认为 true
开启,但是还是需要引入 feign-httpclient
依赖,才能创建 ApacheHttpClient
对象
6.2 使用 OkHttpClient
- 引入
feign-okhttp
依赖
xml
<!-- 引入 Feign Apache HttpClient 依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
- 修改配置
yml
feign:
httpclient:
#是否开启,默认为 true
enabled: false
okhttp:
#是否开启,默认为 false
enabled: true
7. 请求重试
Feign 和 Ribbon 都有请求重试的功能,两者都启用该功能的话,会产生冲突的问题。因此,有且只能启动一个的重试。目前比较推荐的是使用 Ribbon 来提供重试。
在 Spring Cloud OpenFeign 中,默认创建的是 NEVER_RETRY 不进行重试,因此我们只需要配置 Ribbon 的重试功能即可。
yml
ribbon:
#请求的连接超时时间,单位:毫秒。默认为 1000
ConnectTimeout: 1000
#请求的读取超时时间,单位:毫秒。默认为 1000
ReadTimeout: 1
#是否对所有操作都进行重试,默认为 false。
OkToRetryOnAllOperations: true
#对当前服务的重试次数,默认为 0 次。
MaxAutoRetries: 0
#重新选择服务实例的次数,默认为 1 次。注意,不包含第 1 次
MaxAutoRetriesNextServer: 1