【发布时间】:2017-10-30 00:47:45
【问题描述】:
我们通过直接扩展 HystrixCommand 类来使用 Hystrix 功能。但是对于一些业务异常,正在触发Hystrix的fallback方法。
我不想针对某些业务特定异常触发 Hystrix 回退。我如何在没有基于注释的情况下实现它?
【问题讨论】:
我们通过直接扩展 HystrixCommand 类来使用 Hystrix 功能。但是对于一些业务异常,正在触发Hystrix的fallback方法。
我不想针对某些业务特定异常触发 Hystrix 回退。我如何在没有基于注释的情况下实现它?
【问题讨论】:
使用 ignoreExceptions 注释参数
@HystrixCommand(ignoreExceptions = { BaseException.class, MissingServletRequestParameterException.class, TypeMismatchException.class })
见https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#error-propagation
我看到您正在扩展 HystrixCommand 而不是使用注释,但这没关系,只需在命令中设置该属性,它应该具有相同的效果。
不幸的是,Hystrix 命令是由 Builder 模式创建的,因此您必须进行一些黑客操作。在 HystrixCommandBuilder 中使用的 DefaultProperties.java 中添加了 ignoreExceptions
【讨论】:
HystrixCommand 中没有此类属性
如果您将逻辑包装在 try/catch 中并在 HystrixBadRequestException 中重新抛出任何异常,则它不会触发回退。
@Override
protected Object run() throws Exception {
try {
return //call goes here
}
catch (Throwable e) {
//We wrap any exceptions in a HystrixBadRequestException because this way any other errors will not
//trip the short circuit
throw new HystrixBadRequestException("Exception thrown hystrix call", e);
}
}
表示带有提供的参数或状态的错误而不是执行失败的异常。 与 HystrixCommand 抛出的所有其他异常不同,这不会触发回退,不计入故障指标,因此不会触发断路器。
注意:这仅应在错误是由于用户输入(例如 IllegalArgumentException)引起时使用,否则它会破坏容错和回退行为的目的。
【讨论】:
有两种方法可以做到这一点。
使用 HystrixCommand 注解并指定异常类型。
@HystrixCommand(ignoreExceptions = { HttpStatusCodeException.class, JsonMappingException.class })
使用“HystrixBadRequestException”并自定义代码以忽略少数异常情况或状态代码。此实现将检查您的后端 API 合同预期的异常的特定错误代码,并且不会调用 hystrix 回退。抛出“HystrixBadRequestException”不会算作 hystrix 故障。
@HystrixCommand(commandKey = "MyHystrixCommand", fallbackMethod = "myHystrixFallback", threadPoolKey = "ThreadPoolKey")
public ResponseEntity<String> getServiceCallResponse(String serviceUrl, HttpEntity<?> entity) {
ResponseEntity<String> resp = null;
try {
resp = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, String.class)
.getBody();
}
catch(Exception e) {
handleExceptionForHystrix("getServiceCallResponse", e);
}
return resp;
}
private void handleExceptionForHystrix(String function, Exception e) {
if (e instanceof HttpStatusCodeException) {
HttpStatus httpStatusCode = ((HttpStatusCodeException)e).getStatusCode();
if(httpStatusCode.equals(HttpStatus.BAD_REQUEST) || httpStatusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR)) {
throw new HystrixBadRequestException("Hystrix Bad Request Exception Occurred" + httpStatusCode, e);
}
throw new RuntimeException(function, e);
}
throw new RuntimeException(function, e);
}
public ResponseEntity<String> myHystrixFallback(String serviceUrl, HttpEntity<?> entity, Throwable hystrixCommandExp) {
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
}
【讨论】: