如果受 hystrix 保护的调用超时,我可以抛出自定义错误吗?
Posted
技术标签:
【中文标题】如果受 hystrix 保护的调用超时,我可以抛出自定义错误吗?【英文标题】:Can I throw a custom error if a hystrix-protected call times out? 【发布时间】:2016-12-23 23:37:10 【问题描述】:我有一个通过这个外部调用的假客户:
@RequestMapping(method = RequestMethod.GET, value = "GetResourceA", consumes = "application/json")
@Cacheable("ResourceA")
List<Stop> getResourceA() throws MyOwnException;
在我的application.yml
我有这个设置:
hystrix:
command:
default:
execution.isolation.thread.timeoutInMilliseconds: 1000
fallback.enabled: false
现在,如果 getResourceA 超时,即完成时间超过一秒,我要么得到这个:
com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and no fallback available
或者,如果我定义了一个我自己抛出异常的回退,我会得到:
com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and fallback failed.
我不能从回退中抛出自己的异常吗?
如果我想在服务关闭时抛出自己的异常怎么办?我不想有后备(因为我没有从后备返回的合理价值),而是抛出我自己可以捕获的错误并让程序恢复。有人可以帮我解决这个问题吗?
Ben 回答后更新:
所以我尝试了捕获 HysterixRuntimeException 并检查导致它的原因的方法,但最终得到了这个丑陋的代码:
try
getResourceA();
catch (HystrixRuntimeException e)
if (e.getFailureType().name().equals("TIMEOUT"))
throw new MyOwnException("Service timed out");
throw e;
所有这些都能够在超时时抛出 MyOwnException。肯定还有别的办法吗?
【问题讨论】:
【参考方案1】:您应该能够通过获取HystrixRuntimeException
的原因来获取您从回退中抛出的异常
因此,要处理您的自定义异常,您可以这样做:
try
getResourceA();
catch (HystrixRuntimeException e)
if (e.getCause() instanceof MyException)
handleException((MyException)e.getCause());
【讨论】:
谢谢!这就是我要做的,除非有另一种方法不需要我在“我自己的代码”中捕获(丑陋的)HystrixRuntimeException。 @L42。没问题。去年我遇到了同样的问题,这将是我能找到的最好的。很想看看是否有其他人有更好的建议我可以用来整理一下:) 我试过了,最终不得不执行以下操作来检索我在回退方法中抛出的异常:pastebin.com/Dxw95kSB。你知道更好的方法吗? 不,不幸的是,这可能是唯一的方法。您可以创建一个方法并将异常传入,然后检查异常的类型,获取原因并递归调用自身以继续检查异常类型,直到您获得可以使用的异常? 我已经用我想要的东西更新了我的问题。我想我可以将它提取到它自己的函数中:)【参考方案2】:您可以使用 ErrorDecoder 并从那里返回您自己的异常,然后使用异常处理程序。我有一个类似的问题并像这样解决它:
public class ExceptionHandlerControllerAdvice extends ResponseEntityExceptionHandler
...
@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(HystrixRuntimeException.class)
public ExceptionResponse handleHystrixRuntimeException(HystrixRuntimeException exception)
if(exception.getCause() instanceof MyException)
return handleMyException((MyException) exception.getCause());
...
然后在我的 FeignClient 的配置类中:
@Bean
public ErrorDecoder feignErrorDecoder()
return new ErrorDecoder()
@Override
public Exception decode(String methodKey, Response response)
return new MyException("timeout");
;
这样你就不需要多个嵌套的getCause()
【讨论】:
【参考方案3】:如果你想替换hystrix抛出的超时异常,你可以这样写:
try
testClient.timeoutTest();
catch (HystrixRuntimeException e)
Throwable fallbackException = e.getFallbackException();
if (fallbackException.getCause().getCause() instanceof CustomException)
log.info("customer exception!");
【讨论】:
以上是关于如果受 hystrix 保护的调用超时,我可以抛出自定义错误吗?的主要内容,如果未能解决你的问题,请参考以下文章