Spring Cloud OpenFeign 声明式服务调用

Posted by 暮夏有五 on 2021-02-06
Estimated Reading Time 7 Minutes
Words 1.6k In Total
Viewed Times

Feign 简介


Spring Cloud Open Feign 是声明式的服务调用工具,它整合了 Ribbon 和 Hystrix,拥有负载均衡和服务容错功能,本文将对其用法进行详细介绍。

Feign 是声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用 RestTemplate 来调用服务接口的开发量。Feign 具备可插拔的注解支持,同时支持 Feign 注解、JAX-RS 注解及 Spring MVC 注解。当使用 Feign 时,Spring Cloud 集成了 Ribbon 和 Eureka 以提供负载均衡的服务调用及基于 Hystrix 的服务容错保护功能。

创建项目模块


这里我们创建一个 feign-service 模块来演示 feign 的常用功能。

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

相关配置

在 application.yml 中进行配置

1
2
3
4
5
6
7
8
9
10
11
server:
port: 8701
spring:
application:
name: feign-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8001/eureka/

在启动类上添加 @EnableFeignClients 注解来启用 Feign 的客户端功能

1
2
3
4
5
6
7
8
9
10
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignServiceApplication {

public static void main(String[] args) {
SpringApplication.run(FeignServiceApplication.class, args);
}

}

接口绑定

添加 UserService 接口完成对 user-service 服务的接口绑定。我们通过 @FeignClient 注解实现了一个 Feign 客户端,其中的 value 为 user-service 表示这是对 user-service 服务的接口调用客户端。我们可以回想下 user-service 中的 UserController,只需将其改为接口,保留原来的 Spring MVC 注释即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@FeignClient(value = "user-service")
public interface UserService {
@PostMapping("/user/create")
CommonResult create(@RequestBody User user);

@GetMapping("/user/{id}")
CommonResult<User> getUser(@PathVariable Long id);

@GetMapping("/user/getByUsername")
CommonResult<User> getByUsername(@RequestParam String username);

@PostMapping("/user/update")
CommonResult update(@RequestBody User user);

@PostMapping("/user/delete/{id}")
CommonResult delete(@PathVariable Long id);
}

服务调用

添加 UserFeignController 调用 UserService 实现服务调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@RestController
@RequestMapping("/user")
public class UserFeignController {
@Autowired
private UserService userService;

@GetMapping("/{id}")
public CommonResult getUser(@PathVariable Long id) {
return userService.getUser(id);
}

@GetMapping("/getByUsername")
public CommonResult getByUsername(@RequestParam String username) {
return userService.getByUsername(username);
}

@PostMapping("/create")
public CommonResult create(@RequestBody User user) {
return userService.create(user);
}

@PostMapping("/update")
public CommonResult update(@RequestBody User user) {
return userService.update(user);
}

@PostMapping("/delete/{id}")
public CommonResult delete(@PathVariable Long id) {
return userService.delete(id);
}
}

负载均衡功能演示


启动 eureka-service,两个 user-service,feign-service 服务。然后多次调用 http://localhost:8701/user/1 进行测试,可以发现运行在 8201 和 8202 的 user-service 服务交替打印信息。

Feign 中的服务降级

Feign 中的服务降级使用起来非常方便,只需要为 Feign 客户端定义的接口添加一个服务降级处理的实现类即可,下面我们为 UserService 接口添加一个服务降级实现类。

添加服务降级实现类 UserFallbackService

需要注意的是它实现了 UserService 接口,并且对接口中的每个实现方法进行了服务降级逻辑的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Component
public class UserFallbackService implements UserService {
@Override
public CommonResult create(User user) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}

@Override
public CommonResult<User> getUser(Long id) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}

@Override
public CommonResult<User> getByUsername(String username) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}

@Override
public CommonResult update(User user) {
return new CommonResult("调用失败,服务被降级",500);
}

@Override
public CommonResult delete(Long id) {
return new CommonResult("调用失败,服务被降级",500);
}
}

修改 UserService 接口,设置服务降级处理类为 UserFallbackService

修改@FeignClient 注解中的参数,设置 fallbackUserFallbackService.class 即可。

1
2
3
@FeignClient(value = "user-service",fallback = UserFallbackService.class)
public interface UserService {
}

修改 application.yml,开启 Hystrix 功能

1
2
3
feign:
hystrix:
enabled: true #在Feign中开启Hystrix

服务降级功能演示


关闭两个 user-service 服务,重新启动 feign-service。调用 http://localhost:8701/user/1 进行测试,可以发现返回了服务降级信息。

日志打印功能


Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。

日志级别

  • NONE:默认的,不显示任何日志;
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间;
  • HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;
  • FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。

相关配置

我们通过 java 配置来使 Feign 打印最详细的 Http 请求日志信息。

1
2
3
4
5
6
7
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

在 application.yml 中配置需要开启日志的 Feign 客户端。配置 UserService 的日志级别为 debug。

1
2
3
logging:
level:
com.antonio.cloud.service.UserService: debug

查看日志

调用 http://localhost:8701/user/1 进行测试,可以看到以下日志。

1
2
3
4
5
6
7
8
9
2019-10-04 15:44:03.248 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] ---> GET http://user-service/user/1 HTTP/1.1
2019-10-04 15:44:03.248 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] ---> END HTTP (0-byte body)
2019-10-04 15:44:03.257 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] <--- HTTP/1.1 200 (9ms)
2019-10-04 15:44:03.257 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] content-type: application/json;charset=UTF-8
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] date: Fri, 04 Oct 2019 07:44:03 GMT
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] transfer-encoding: chunked
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser]
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] {"data":{"id":1,"username":"macro","password":"123456"},"message":"操作成功","code":200}
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService : [UserService#getUser] <--- END HTTP (92-byte body)

Feign 的常用配置


Feign 自己的配置

1
2
3
4
5
6
7
8
9
10
11
12
feign:
hystrix:
enabled: true #在Feign中开启Hystrix
compression:
request:
enabled: false #是否对请求进行GZIP压缩
mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
min-request-size: 2048 #超过该大小的请求会被压缩
response:
enabled: false #是否对响应进行GZIP压缩
logging:
level: #修改日志级别

Feign 中的 Ribbon 配置

在 Feign 中配置 Ribbon 可以直接使用 Ribbon 的配置。

Feign 中的 Hystrix 配置

在 Feign 中配置 Hystrix 可以直接使用 Hystrix 的配置。

更多干货请移步:https://antoniopeng.com


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !