为什么要学习Feign?

答:简化 远程代码调用

我们使用了Ribbon的负载均衡功能,大大简化了远程调用时的代码:

1
2
String baseUrl = "http://user-service/user/";
User user = this.restTemplate.getForObject(baseUrl + id, User.class)

我们在这里仍然可能会面临大量的重复代码的问题,其实这依然是有解决方案的。

这就是我们接下来要学的Feign的功能了。

feign这个东西相当于前面学到的resttempalte 和 httptemplate 差不多,实质上就是对resttemplate进行又高一级的封装

导入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

开启Feign功能

我们在启动类上,添加注解,开启Feign功能

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients // 开启Feign功能
public class UserConsumerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerDemoApplication.class, args);
}
}
  • 这里我们已然无需注册rest template了,

Feign的客户端

1
2
3
4
5
6
@FeignClient("user-service")
public interface UserFeignClient {

@GetMapping("/user/{id}")
User queryUserById(@PathVariable("id") Long id);
}
  • 首先这是一个接口,可以独立的创建一个包,Feign会通过动态代理,帮我们生成实现类。
  • @FeignClient,声明这是一个Feign客户端,类似@Mapper注解。同时通过value属性指定服务名称
  • 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果

改造原来的调用逻辑,修改UserDao:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Autowired
private UserFeighClient userFeighClient;


@HystrixCommand(fallbackMethod = "queryUserByIdFallback")
public User queryUserById(Long id){
long begin = System.currentTimeMillis();

User user = this.userFeighClient.queryById(id);

long end = System.currentTimeMillis();
System.out.println("用时:"+(begin-end));

return user;
}

因此我们不需要额外引入依赖,也不需要再注册RestTemplate对象。

负载均衡

我们可以像上节课中讲的那样去配置Ribbon,可以通过ribbon.xx来进行全局配置。也可以通过服务名.ribbon.xx来对指定服务配置:

  • 全局配置:对所有服务都生效
1
2
3
4
5
6
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 1000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
  • 局部配置:只对当前服务生效
1
2
3
4
5
6
7
user-service:
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 1000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数

熔断器

Feign默认也有对Hystrix的集成,只不过,默认情况下是关闭的。我们需要通过下面的参数来开启:

1
2
3
feign:
hystrix:
enabled: true # 开启Feign的熔断功能

但是,Feign中的Fallback配置不像Ribbon中那样简单了。

1)首先,我们要定义一个类,实现刚才编写的UserFeignClient,作为fallback的处理类

1
2
3
4
5
6
7
8
9
10
11
@Component
public class UserFeignClientFallback implements UserFeignClient {
@Override
public User queryUserById(Long id) {
User user = new User();
user.setId(id);
user.setName("用户查询出现异常!");
return user;
}
}

2)然后在UserFeignClient中,指定刚才编写的实现类

1
2
3
4
5
6
7
@FeignClient(value = "user-service", fallback = UserFeignClientFallback.class)
public interface UserFeignClient {

@GetMapping("/user/{id}")
User queryUserById(@PathVariable("id") Long id);
}

压缩

GZIP压缩:

Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能:

1
2
3
4
5
6
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩

同时,我们也可以对请求的数据类型,以及触发压缩的大小下限进行设置:

1
2
3
4
5
6
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限

注:上面的数据类型、压缩大小下限均为默认值。

总结:

feign非常强,综合了负载均衡,熔断器等功能,本来