接上篇《19.Hystrix Health Indicator及Metrics Stream支持》 Spring Cloud版本为Finchley.SR2版
上一篇我们简单介绍了Hystrix的健康指数监控以及API监控,分别用来查看Hystrix断路器的状态,以及应用API服务的详细监控情况。本篇我们来讲解如何在Feign组件中使用Hystrix。
本部分官方文档:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html
之前我们讲过,Feign组件是用来实现声明式服务调用功能的,换句话说就是Feign可以优雅的调用REST风格的服务。我们回顾一下之前的Feign组件的使用过程:
首先我们在Movie工程的Controller中通过userFeignClient接口对象,去调用findById方法,而此方法就是通过Feign组件进行远程REST服务的调用:
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/movie/{id}")
@HystrixCommand(fallbackMethod = "findUserByIdFallback",
commandProperties = {@HystrixProperty(name="execution.isolation.strategy",value="SEMAPHORE")})
public User findUserById(@PathVariable Long id){
return userFeignClient.findById(id);
}
public User findUserByIdFallback(Long id){
User user = new User();
user.setId(0L);
return user;
}
这里UserFeignClient接口就封装了Feign组件的实现:
package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;
@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class )
public interface UserFeignClient {
@RequestLine("GET /findById/{id}")
public User findById(@Param("id") Long id);
@RequestLine("POST /postUser")
public String postUser(@RequestBody User user);
}
这里我们在接口头部仅需要定义@FeignClient,以及要调用的远程服务的实例名,配置类信息即可。在每个方法定义上,添加@RequestLine注解,来定义该服务的请求类型以及实际请求URL。
这样实现了一个Feign组件调用远程服务的效果。
在上面的例子中,我们加入Hystrix实现断路器的方式是,在调用userFeignClient之前的Controller方法中添加@HystrixCommand以及降级方法fallbackMethod,其实如果我们要单纯的处理findById方法的断路降级问题,直接在UserFeignClient接口中,即在Feign组件中实现Hystrix断路器即可。
下面我们在Feign中实现Hystrix断路器。
Spring Cloud默认已为Feign整合了Hystrix,只要Hystrix在项目的classpath中,Feign默认就会用断路器包裹所有方法。
如果要使用Feign的Hystrix支持,可以设置feign.hystrix.enabled=true,要禁用,设置为false即可。
我们可以通过以下方式来实现Feign的Hystrix支持:
1、@FeignClient注解配置fallback参数,实现FeignClient接口
我们可以在之前的FeignClient接口上的@FeignClient添加fallback参数,该参数是一个FeignClient接口的实现类,在实现类中实现FeignClient接口中的各个方法即可。
当FeignClient接口中的服务调用失败,触发断路器打开,请求转移的降级服务,就是FeignClient接口实现类中的同名方法。
我们来实现这个效果。首先在Movie工程的application.yml配置文件中开启Feign的Hystrix支持:
feign:
hystrix:
enabled: true
然后修改一下之前的Controller类以及UserFeignClient接口,使其实现Feign对Hystrix的支持:
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/movie/{id}")
public User findUserById(@PathVariable Long id){
return userFeignClient.findById(id);
}
UserFeignClient接口:
package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;
@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class,
fallback = FeignClientFallback.class )
public interface UserFeignClient {
@RequestLine("GET /findById/{id}")
public User findById(@Param("id") Long id);
@RequestLine("POST /postUser")
public String postUser(@RequestBody User user);
}
@Component
class FeignClientFallback implements UserFeignClient{
@Override
public User findById(Long id) {
User user = new User();
user.setId(0L);
user.setName("FeignClient 降级服务");
return user;
}
@Override
public String postUser(User user) {
return null;
}
}
可以看到,我们在fallback中定义了降级实现类FeignClientFallback,然后编写了该内部类,实现了UserFeignClient接口,然后实现接口中的每一个方法,定义降级服务的内容,其中findById的内容,和之前在Controller中的“findUserByIdFallback”方法内容相同,这里我们将默认的user对象的name定义为“FeignClient 降级服务”,为了测试证明该服务是Feign组件触发的。
这里我们启动之前的服务提供者user工程、服务消费者movie工程以及eureka Server注册中心,访问“movie/1”服务是好的:
然后关掉服务提供者user工程,再次访问“movie/1”服务,可以看到此时进入了降级服务中:
打印的name内容就是之前降级服务中定义的内容,证明我们通过Feign调用Hystrix成功!
2、@FeignClient注解配置fallbackFactory参数,实现FallbackFactory接口
fallbackFactory参数指定一个fallback工厂,与指定fallback不同, 此工厂可以用来获取到触发断路器的异常信息,fallback工厂类需要实现FallbackFactory类。我们修改一下之前的UserFeignClient,来实现FallbackFactory的断路效果:
package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;
import feign.hystrix.FallbackFactory;
@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class,/*fallback = FeignClientFallback.class*/
fallbackFactory=FeignClientFallbackFactory.class)
public interface UserFeignClient {
@RequestLine("GET /findById/{id}")
public User findById(@Param("id") Long id);
@RequestLine("POST /postUser")
public String postUser(@RequestBody User user);
}
@Component
class FeignClientFallbackFactory implements FallbackFactory{
//日志对象
private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
@Override
public UserFeignClient create(Throwable cause) {
return new UserFeignClient() {
@Override
public User findById(Long id) {
// 日志最好放在各个fallback方法中,而不要直接放在create方法中。
// 否则在引用启动时,就会打印该日志
FeignClientFallbackFactory.LOGGER.info("fallback; reason was: ", cause);
User user = new User();
user.setId(0L);
user.setName("FeignClient 降级服务");
return user;
}
@Override
public String postUser(User user) {
return null;
}
};
}
}
可以看到,我们指定的fallbackFactory参数对应的内部类,实现了FallbackFactory
我们按照之前的方式,只启动服务消费者movie工程和eureka Server注册中心,不启动服务提供者user工程,此时访问“movie/1”服务:
然后我们在编译器的控制台可以看到:
说明请求不仅进入了降级服务,而且打印出了详细的异常信息,这里的异常主要是microserver-provider-user服务不可用,其实是我们的服务提供者没有启动造成的。
总的来说,fallback工厂类的优点是可以通过Throwable对象获取到异常信息。
至此,Feign对支持Hystrix支持相关的知识就介绍到这里了。
参考:《51CTO学院Spring Cloud高级视频》
转载请注明出处:https://blog.csdn.net/acmman/article/details/101864536