文章目录
- 1. Feign 是什么
- 2. Feign 的使用
- 2.1 引入依赖
- 2.2 写接口
- 2.3 服务调用方
- 2.4 启动测试
- 3. Feign 日志配置
- 4. Feign 使用优化
- 5. 注意包扫描问题
- 6. 注意的问题
- 6.1 参数问题
- 6.2 Feign 自动装配
1. Feign 是什么
Feign
是一个声明式、模板化的 HTTP 客户端,它是由 Netflix 开发并开源的。Feign 极大地简化了基于 HTTP 的服务间通信的开发过程,并与 Spring Cloud 进行了深度集成。
以下是 Feign 的一些特点和优势:
-
声明式 API 定义:Feign 使用接口的方式定义服务调用的 API,使得声明和使用 API 更加直观和简洁。你只需要定义接口,并使用注解来描述 API 的细节,如请求方法、请求路径、请求参数等信息。
-
整合了负载均衡:在 Spring Cloud 环境下,Feign 可以与 Ribbon 负载均衡进行集成。它可以自动将请求分发到后端的多个服务实例中,以实现负载均衡和服务发现。
-
集成了 Hystrix 断路器:Feign 直接集成了 Hystrix 断路器,可以提供服务降级和容错能力。当服务调用失败或延迟过高时,Feign 可以快速启动断路器,避免雪崩效应。
-
支持多种编码器和解码器:Feign 支持多种数据格式的编码和解码,例如 JSON、XML 等。你可以通过配置和注解来指定请求和响应的编码方式。
-
支持自定义拦截器:Feign 提供了拦截器的扩展机制,你可以在请求发出前或响应返回后对请求进行处理。这些拦截器可以用于日志记录、认证授权、请求重试等逻辑。
Feign 提供了一种简单、高效的方式来定义和使用 HTTP 客户端。它基于接口和注解,使得服务之间的调用更加直观和易于维护。同时,Feign 还集成了负载均衡和断路器等功能,可以帮助开发者构建高可用和可靠的微服务架构。
微服务之间的远程调用可以用 RestTemplate
来发起远程调用. 但是存在下面的几个问题:
•代码可读性差,编程体验不统一
•参数复杂URL难以维护
Feign
的作用就是帮助我们优雅的实现 http 请求的发送,解决上面提到的问题。
2. Feign 的使用
在实际的项目开发中我们会把各个微服务提供的供其他服务远程调用的接口 封装在一个单独的服务里.
2.1 引入依赖
在 API 服务;里引入依赖
<!--feign客户端依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
2.2 写接口
参照 服务提供的接口 写 API 中的接口
@FeignClient("user-server")
public interface UserApi {@GetMapping("user/{userId}")String hello(@PathVariable("userId") Integer userId);}
user-server 是微服务的服务名
2.3 服务调用方
服务调用方要做如下改动:
-
引入依赖
<dependency><groupId>com.snow</groupId><artifactId>api</artifactId><version>1.0-SNAPSHOT</version></dependency>
-
启动类加配置
启动类上加一行配置@EnableFeignClients(basePackages = {"com.snow.api"})
com.snow.api 表示 API 的包
-
实际调用
2.4 启动测试
略…
3. Feign 日志配置
基于配置文件修改feign的日志级别可以针对单个服务:
feign: client:config: user-server: # 针对某个微服务的配置loggerLevel: FULL # 日志级别
也可以针对所有服务:
feign: client:config: default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置loggerLevel: FULL # 日志级别
而日志的级别分为四种:
- NONE:不记录任何日志信息,这是默认值。
- BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
- HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
- FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
4. Feign 使用优化
Feign 底层发起 http 请求,依赖于其它的框架。其底层客户端实现包括:
• URLConnection:默认实现,不支持连接池
• Apache HttpClient :支持连接池
• OKHttp:支持连接池
因此提高 Feign 的性能主要手段就是使用 连接池 代替默认的 URLConnection。
这里我们用 Apache 的 HttpClient 来演示。
1)引入依赖
在 order-server 的 pom 文件中引入 Apache 的 HttpClient 依赖:
<!--httpClient的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>
2)配置连接池
在 order-server 的 application.yml 中添加配置:
feign:client:config:default: # default全局的配置loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息httpclient:enabled: true # 开启feign对HttpClient的支持max-connections: 200 # 最大的连接数max-connections-per-route: 50 # 每个路径的最大连接数
接下来,在 FeignClientFactoryBean 中的 loadBalance 方法中打断点:
Debug方式启动order-service服务,可以看到这里的client,底层就是Apache HttpClient:
5. 注意包扫描问题
服务调用方的启动类上.
方式一:
指定 Feign 应该扫描的包:
@EnableFeignClients(basePackages = "com.snow.api")
方式二:
指定需要加载的 Client 接口:
@EnableFeignClients(clients = {UserApi.class})
6. 注意的问题
6.1 参数问题
通过 Feign 调用的接口, 方法的参数需要明确告诉参数的名称,像下面的方式是不行滴!
Integer get(Integer age, String name){
}
改为下面的方式
Integer get(@RequestParam("age") Integer age, @RequestParam("name") String name){
}
6.2 Feign 自动装配
(注意 该方法可能在 SpringBoot2.7 及其高版本失效)
在之前的实践中, 我们的消费者启动类加了 @EnableFeignClients(basePackages = {"com.snow.api"})
注解, 其非常的不雅观, 并且耦合性有点强.
我们可以用 Feign 自动装配 来代替之前的做法.
- 首先我们在 API 微服务下的
resource
包下面创建一个文件夹META-INF
,然后在其下面建spring.factories
配置文件 . 如下图:
- 在 配置类上 加注解
@Configuration
@EnableFeignClients(basePackages = {"com.snow.api"})
- 在 spring.factories 文件里编辑
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.snow.api.conf.ApiConfig
其中 com.snow.api.conf.ApiConfig
就是配置类全路径.
4 .启动,测试
效果很 OK.
如此以来,我们有新的 API 发布,都不会再去 API 使用方的启动类上加东西了.