本文为《Spring Cloud微服务实战》一书的摘要总结
开始使用
Feign整合了Ribbon和Hystrix,同时还提供了一种声明式的Web服务客户端定义方式。
- 创建一个SpringBoot应用,加入依赖:
<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-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
-
在主类上添加
@EnableDiscoveryClient
和@EnableFeignClients
注解 -
创建一个服务接口:
@FeignClient("SERVER-HELLO")//指定被调用服务应用名
public interface HelloService {
@RequestMapping("/home")//服务路径,Feign支持SpringMVC的注解
String home();
}
- 调用服务
public class Test {
@Autowired
private HelloService helloService;
public String home() {
return helloService.home();
}
}
然后调用HelloService.home()
,就可以实现对"http://SERVER-HELLO/home"服务的调用。这里依然使用Ribbon维护了针对SERVER-HELLO的服务列表,
并且通过轮询实现了客户端负载均衡。
参数绑定
@FeignClient("SERVER-HELLO")
public interface HelloService {
@RequestMapping("/home")
String home();
@GetMapping("/hello1")
String hello(@RequestParam("name") String name);//入参name作为请求参数追加在url之后
@GetMapping("/hello2")
Employees hello(@RequestHeader("first_name") String first_name, @RequestHeader("last_name") String last_name );//将在请求头中添加first_name,和last_name两个参数
@PostMapping("/hello3")
String hello(@RequestBody Employees employees);//将在请求体中添加Employees实例
}
我们甚至可以从服务方的Controller中复制这些方法签名以及其注解。也可以将接口以及一些公共类都打包成单独的maven项目,然后服务提供方和消费放都依赖这个包。
Ribbon配置
-
全局配置:
ribbon.= -
指定服务配置
.ribbon.=
我们在使用@FeignClient
注解接口时,Feign就会根据该注解的name
或者value
属性自动创建一个同名Ribbon客户端。所以前面我们使用@Feign("SERVER-HELLO")
注解接口时,就创建了一个名为SERVER-HELLO
的Ribbon客户端
Hystrix配置
默认情况下,Spring Cloud Feign会将所有Feign客户端的方法都封装到Hystrix命令中进行服务保护。
feign.hystix.enabled=false # 关闭hystrix
全局配置:使用hystrix.comand.defalut
前缀。
如果不想全局禁用Hystrix,而只是想对某个服务客户端关闭Hystrix支持:
@Configuration
public class DisableHystrixConfiguration{
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder(){
return new Feign.Builder();
}
}
@FeignClient(name="SERVER-HELLO",configuration = DisableHystrixConfiguration.class)
public interface HelloService{
...
}
指定命令配置
采用hystrix.command.<commandKey>
作为前缀,而<commandKey>
默认情况下采用Feign客户端中的方法名作为标识。
服务降级配置
- 只需要为Feign客户端的定义接口编写一个具体的实现类,其中实现的方法就是具体的服务降级逻辑。
public class HelloServiceFallback implements HelloService{
public String home(){
return "error";
}
public String hello1(@RequestParam("name") String name){
return "error"
}
...
}
- 在服务绑定接口
HelloService
中,通过@FeignClient
注解的fallbak
属性来指定对应的服务降级实现类。
@FeignClient(name = "SERVER-HELLO",fallback = HelloServiceFallback.class)
public interface HelloService{
@RequestMapping("/home")
String home();
@GetMapping("/hello1")
String hello(@RequestParam("name") String name);
@GetMapping("/hello2")
Employees hello(@RequestHeader("first_name") String first_name, @RequestHeader("last_name") String last_name );
@PostMapping("/hello3")
String hello(@RequestBody Employees employees);
}
日志配置
Spring Cloud Feign在构建被@FeignClient
注解修饰的服务客户端时,会为每一个客户端都创建一个feign.Logger实例,我们可以利用该日志对象的DEBUG模式来帮助分析Feign的请求细节。
在配置文件中使用logging.level.<FeignClient>
的参数配置格式来开启指定Feign客户端DEBUG日志,其中为Feign客户端定义接口的完整路径,如:
loggin.level.com.canwin.service.HelloService=DEBUG
因为Feign客户端默认的Logger.Level
对象定义为NONE
级别,该级别不会输出任何日志;所以我们需要调整它的级别。
针对全局日志级别:我们可以在主类中配置Logger.Level
bean:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignConsumerApplication {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApplication.class, args);
}
}
针对指定的客户端,我们也可以通过实现配置类,然后在具体的Feign客户端来指定配置类,从而实现不同客户端不同的日志界别:
@Configuration
public class LoggerLevel_FULLConfig{
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
@FeignClient(name="SERVER-HELLO",configuration=com.canwin.config.LoggerLevel_FULLConfig.class)
public interface HelloServic{
...
}
Feign的Logger级别主要有下面4类:
- NONE:不记录任何信息
- BASIC:仅记录请求方法、url,已经响应状态码和时间
- HEADERS:除了记录BASIC级别的信息外,还会记录请求和响应头的信息
- FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据等。