在@HystrixCommand 回退方法中获取失败异常
Posted
技术标签:
【中文标题】在@HystrixCommand 回退方法中获取失败异常【英文标题】:Get failure exception in @HystrixCommand fallback method 【发布时间】:2015-12-26 03:32:23 【问题描述】:在 Spring Boot 应用程序中使用 @HystrixCommand
注释时,有没有办法获取 HystrixCommand
失败的原因?看起来如果您实现自己的HystrixCommand
,您可以访问getFailedExecutionException
,但是在使用注释时如何访问它?我希望能够根据发生的异常类型在回退方法中做不同的事情。这可能吗?
我看到了一个关于 HystrixRequestContext.initializeContext()
的 note,但 HystrixRequestContext
不能让您访问任何内容,是否有其他方法可以使用该上下文来访问异常?
【问题讨论】:
【参考方案1】:只需在回退方法中添加一个 Throwable 参数,它就会收到原始命令产生的异常。
来自https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica
@HystrixCommand(fallbackMethod = "fallback1")
User getUserById(String id)
throw new RuntimeException("getUserById command failed");
@HystrixCommand(fallbackMethod = "fallback2")
User fallback1(String id, Throwable e)
assert "getUserById command failed".equals(e.getMessage());
throw new RuntimeException("fallback1 failed");
【讨论】:
对于Throwable e
,它可以告诉我真正的原因,例如FAILURE/SHORTCIRCUITED/TIMEOUT/BAD_REQUEST/SEMAPHORE_REJECTED/THREAD_POOL_REJECTED。有人说他们不能,因为他们需要调整 javanica 以使用 getExecutionException() 而不是 @vicco 提到的 getFailedExecutionException()。【参考方案2】:
我也没有找到使用注释获取异常的方法,但是创建我自己的命令对我很有效:
public static class DemoCommand extends HystrixCommand<String>
protected DemoCommand()
super(HystrixCommandGroupKey.Factory.asKey("Demo"));
@Override
protected String run() throws Exception
throw new RuntimeException("failed!");
@Override
protected String getFallback()
System.out.println("Events (so far) in Fallback: " + getExecutionEvents());
return getFailedExecutionException().getMessage();
希望这对其他人也有帮助。
【讨论】:
【参考方案3】:正如文档中所说的Hystrix-documentation getFallback()
方法将在以下情况下被抛出:
-
当命令执行失败时:当construct()或run()抛出异常时
当命令因为电路开路而短路时
当命令的线程池和队列或信号量满时
当命令超过其超时长度时。
因此,您可以通过将执行异常分配给 Throwable 对象,轻松获取引发您调用的回退方法的原因。
假设你的 HystrixCommand 返回一个字符串
public class ExampleTask extends HystrixCommand<String>
//Your class body
如下操作:
@Override
protected ErrorCodes getFallback()
Throwable t = getExecutionException();
if (circuitBreaker.isOpen())
// Log or something
else if (t instanceof RejectedExecutionException)
// Log and get the threadpool name, could be useful
else
// Maybe something else happened
return "A default String"; // Avoid using any HTTP request or ypu will need to wrap it also in HystrixCommand
更多信息here
【讨论】:
【参考方案4】:我找不到通过注释获取异常的方法,但我找到了HystrixPlugins
,你可以注册一个HystrixCommandExecutionHook
,你可以像这样得到确切的异常:
HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixCommandExecutionHook()
@Override
public <T> void onFallbackStart(final HystrixInvokable<T> commandInstance)
);
命令实例是GenericCommand
。
【讨论】:
但这通常会在每次执行命令时捕获它们,并且不会与特定的命令执行相关联,对吗?不完全是我所追求的,但在您需要了解失败的某些情况下仍然可能会有所帮助。【参考方案5】:大多数时候只是使用 getFailedExecutionException().getMessage() 给了我空值。
Exception errorFromThrowable = getExceptionFromThrowable(getExecutionException());
String errMessage = (errorFromThrowable != null) ? errorFromThrowable.getMessage()
这总是给我更好的结果。
【讨论】:
以上是关于在@HystrixCommand 回退方法中获取失败异常的主要内容,如果未能解决你的问题,请参考以下文章
如何说 Hystrix 不会为 Hystrix 命令中的某些异常触发回退
深入浅出SpringCloud原理及实战「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的回退降级实现方案和机制