如需转载,请根据 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 许可,附上本文作者及链接。
本文作者: 执笔成念
作者昵称: zbcn
本文链接: https://1363653611.github.io/zbcn.github.io/2021/01/06/springcloud-06OpenFeign/
Spring Cloud OpenFeign:基于Ribbon和Hystrix的声明式服务调用
Spring Cloud OpenFeign 是声明式的服务调用工具,它整合了Ribbon和Hystrix,拥有负载均衡和服务容错功能,本文将对其用法进行详细介绍。
Feign 简介
Feign是声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用RestTemplate来调用服务接口的开发量。Feign具备可插拔的注解支持,同时支持Feign注解、JAX-RS注解及SpringMvc注解。当使用Feign时,Spring Cloud集成了Ribbon和Eureka以提供负载均衡的服务调用及基于Hystrix的服务容错保护功能。
创建一个feign-service模块
这里我们创建一个feign-service模块来演示feign的常用功能。
在pom文件中添加依赖
1 | <dependency> |
2 | <groupId>org.springframework.cloud</groupId> |
3 | <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
4 | </dependency> |
5 | <dependency> |
6 | <groupId>org.springframework.cloud</groupId> |
7 | <artifactId>spring-cloud-starter-openfeign</artifactId> |
8 | </dependency> |
9 | <dependency> |
10 | <groupId>org.springframework.boot</groupId> |
11 | <artifactId>spring-boot-starter-web</artifactId> |
12 | </dependency> |
在application.yml中进行配置
1 | server: |
2 | port: 8701 |
3 | spring: |
4 | application: |
5 | name: feign-server |
6 | eureka: |
7 | client: |
8 | register-with-eureka: true |
9 | fetch-registry: true |
10 | service-url: |
11 | defaultZone: http://localhost:8001/eureka/ |
在启动类上添加@EnableFeignClients注解来启用Feign的客户端功能
1 | //开启声明式服务调用功能 |
2 |
|
3 |
|
4 | public class FeignServerApplication { |
5 | public static void main(String[] args) { |
6 | SpringApplication.run(FeignServerApplication.class, args); |
7 | } |
8 | } |
添加UserService接口完成对user-service服务的接口绑定
1 | "user-service") (value = |
2 | public interface UserService { |
3 | |
4 | "/user/create") ( |
5 | ResponseResult create(@RequestBody User user); |
6 | |
7 | "/user/{id}") ( |
8 | ResponseResult<User> getUser(@PathVariable Long id); |
9 | |
10 | "/user/getByUsername") ( |
11 | ResponseResult<User> getByUsername(@RequestParam String username); |
12 | |
13 | "/user/update") ( |
14 | ResponseResult update(@RequestBody User user); |
15 | |
16 | "/user/delete/{id}") ( |
17 | ResponseResult delete(@PathVariable Long id); |
18 | } |
添加UserFeignController调用UserService实现服务调用
1 |
|
2 | "/user") ( |
3 | public class UserFeignController { |
4 | |
5 | |
6 | private UserService userService; |
7 | |
8 | "/{id}") ( |
9 | public ResponseResult<User> getUser(@PathVariable Long id) { |
10 | return userService.getUser(id); |
11 | } |
12 | |
13 | "/getByUsername") ( |
14 | public ResponseResult getByUsername(@RequestParam String username) { |
15 | return userService.getByUsername(username); |
16 | } |
17 | |
18 | "/create") ( |
19 | public ResponseResult create(@RequestBody User user) { |
20 | return userService.create(user); |
21 | } |
22 | |
23 | "/update") ( |
24 | public ResponseResult update(@RequestBody User user) { |
25 | return userService.update(user); |
26 | } |
27 | |
28 | "/delete/{id}") ( |
29 | public ResponseResult delete(@PathVariable Long id) { |
30 | return userService.delete(id); |
31 | } |
32 | } |
负载均衡功能演示
启动eureka-service,两个user-service,feign-service服务.
多次调用http://localhost:8701/user/1进行测试,可以发现运行在8201和8202的user-service服务交替打印
Feign中的服务降级
Feign中的服务降级使用起来非常方便,只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可,下面我们为UserService接口添加一个服务降级实现类。
添加服务降级实现类UserFallbackService
需要注意的是它实现了UserService接口,并且对接口中的每个实现方法进行了服务降级逻辑的实现。
1 |
|
2 | public class UserFallbackService implements UserService { |
3 | |
4 | public ResponseResult create(User user) { |
5 | return null; |
6 | } |
7 | |
8 | |
9 | public ResponseResult<User> getUser(Long id) { |
10 | User defaultUser = new User(-1L, "defaultUser"); |
11 | return ResponseResult.success(defaultUser); |
12 | } |
13 | |
14 | |
15 | public ResponseResult<User> getByUsername(String username) { |
16 | User defaultUser = new User(-1L, "defaultUser"); |
17 | return ResponseResult.success(defaultUser); |
18 | } |
19 | |
20 | |
21 | public ResponseResult update(User user) { |
22 | return ResponseResult.fail("服务调用失败。。。"); |
23 | } |
24 | |
25 | |
26 | public ResponseResult delete(Long id) { |
27 | return ResponseResult.fail("服务调用失败。。。"); |
28 | } |
29 | } |
修改UserService接口,设置服务降级处理类为UserFallbackService
修改@FeignClient注解中的参数,设置fallback为UserFallbackService.class即可。
1 | "user-service",fallback = UserFallbackService.class) (value = |
2 | public interface UserService { |
3 | } |
修改application.yml,开启Hystrix功能
1 | feign: |
2 | hystrix: |
3 | 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 | public class FeignConfig { |
3 | |
4 | Logger.Level feignLoggerLevel() { |
5 | return Logger.Level.FULL; |
6 | } |
7 | } |
在application.yml中配置需要开启日志的Feign客户端
配置UserService的日志级别为debug。
1 | logging: |
2 | level: |
3 | com.macro.cloud.service.UserService: debug |
查看日志
Feign的常用配置
1 | feign: |
2 | hystrix: |
3 | enabled: true #在Feign中开启Hystrix |
4 | compression: |
5 | request: |
6 | enabled: false #是否对请求进行GZIP压缩 |
7 | mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型 |
8 | min-request-size: 2048 #超过该大小的请求会被压缩 |
9 | response: |
10 | enabled: false #是否对响应进行GZIP压缩 |
11 | logging: |
12 | level: #修改日志级别 |
13 | com.zbcn.feignserver.api.UserService: debug |
Feign中的Ribbon配置
在Feign中配置Ribbon可以直接使用Ribbon的配置,具体可以参考:Spring Cloud Ribbon:负载均衡的服务调用
Feign中的Hystrix配置
在Feign中配置Hystrix可以直接使用Hystrix的配置,具体可以参考:Spring Cloud Hystrix:服务容错保护
使用到的模块
1 | ZBCN-SERVER |
2 | ├── zbcn-register/eureka-server -- eureka注册中心 |
3 | ├── zbcn-business/user-service -- 提供User对象CRUD接口的服务 |
4 | └── zbcn-common/ feign-server -- feign服务调用测试服务 |