之前我们用过了fallbackMethod这个东西,本文将详细说一下这个东西,也就是服务降级
服务降级
前文中,fallbackMethod所描述的函数,就是一个备胎,用来实现服务的降级处理,在@HystrixCommand
注解中,可以通过fallbackMethod来指定请求失败后调用的方法,在自定义的Hystrix请求命令时, 可以通过重写getFallback()方法来处理服务降级之后的逻辑
使用@HystrixCommand
注解指定fallbackMethod方法时,指定的方法要和注解处在同一个类中
指定的这个fallbackMethod方法在执行的过程中,也可能会发生异常,同理我们也可以给这个方法使用@HystrixCommand
注解,指定fallbackMethod,比如这样:1
2
3
4
5
6
7
8
9
10
11
12@HystrixCommand(fallbackMethod = "helloFallback")
public String helloService(){
return restTemplate.getForObject("http://EUREKA-CLIENT/dc", String.class);
}
@HystrixCommand(fallbackMethod = "fallback2")
public String helloFallback(){
return "error";
}
public String fallback2(){
return "error2";
}
实际使用中,只给必要的方法添加断路器就好了.
异常处理
在调用服务提供者的时候,也可能会出现异常,默认情况下,方法抛了异常就会自动进行服务降级,交给服务降级中的方法去处理,下面看下两种Hystrix请求方式下如何捕捉异常
自定义的Hystrix请求方式
在自定义的Hystrix请求方式下,可以在getFallback中捕捉抛出的异常,修改我们之前的StringCommand类,代码如下: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@Slf4j
public class StringCommand extends HystrixCommand<String> {
private RestTemplate restTemplate;
@Override
protected String getFallback() {
Throwable executionException = getExecutionException();
log.info("Exception:{}", executionException.getMessage());
return new String("StringCommand.getFallback");
}
public StringCommand(Setter setter, RestTemplate restTemplate) {
super(setter);
this.restTemplate = restTemplate;
}
@Override
protected String run() throws Exception {
// 这里就会抛异常,然后我们通过getFallback()方法 捕捉这里抛出的异常
int i = 1 / 0;
return restTemplate.getForObject("http://EUREKA-CLIENT/dc", String.class);
}
}
这里就是在,run()方法中int i = 1 / 0;
会抛一个异常,然后我们在getFallback()方法中通过Throwable executionException = getExecutionException();
来捕获异常.
之后还是通过http://localhost:9000/testStringCommand来测试.
页面返回:
控制台输出:1
2019-02-21 16:54:45.735 INFO 8324 --- [ hystrix--1] c.eureka.consumer.hystrix.StringCommand : Exception:/ by zero
这里就已经进行了服务降级
使用注解的方式
如果是用了注解,只需要在服务降级的方法中添加一个,Throwable类型的参数即可,具体代码如下:1
2
3
4
5
6
7
8
9
10@HystrixCommand(fallbackMethod = "helloFallback")
public String helloService(){
int i = 1 / 0;
return restTemplate.getForObject("http://EUREKA-CLIENT/dc", String.class);
}
public String helloFallback(Throwable throwable){
log.info("Exception:{}", throwable.getMessage());
return "error";
}
将异常抛给用户
如果有一个异常,我们并不希望进入到服务降级的方法中,而是想让他直接抛给用户,么可以在@HystrixCommand
注解中添加异常忽略,代码如下:1
2
3
4
5
6
7
8
9
10@HystrixCommand(fallbackMethod = "helloFallback",ignoreExceptions = ArithmeticException.class)
public String helloService(){
int i = 1 / 0;
return restTemplate.getForObject("http://EUREKA-CLIENT/dc", String.class);
}
public String helloFallback(Throwable throwable){
log.info("Exception:{}", throwable.getMessage());
return "error";
}
然后再次调用,执行结果如下:
这里可以看到,并没有服务降级,而是直接把错误抛给了用户.
这里的实现原理很简单,因为有一个名叫HystrixBadRequestException的异常不会进入到服务降级方法中去,当我们定义了ignoreExceptions为ArithmeticException.class之后,当抛出ArithmeticException异常时,Hystrix会将异常信息包装在HystrixBadRequestException里边然后再抛出,此时就不会触发服务降级方法了。