背景:公司项目目前通过RestTemplate封装了RPC调用,现在要集成Hystrix做熔断和限流。
首先,新建类继承HystrixCommand抽象类,重写run()和getFallback()方法。
其中,run方法做业务处理,即通过restTemplate发送请求;getFallback方法,作为降级处理的方法。
但是降级处理,如果只返回失败,不能区分具体的失败原因,会影响后期的问题排除,所以必须知道业务处理返回的具体异常。
HystrixCommand的父类AbstractCommand,提供了获取异常的方法getExecutionException()
/**
* Get the Throwable/Exception emitted by this command instance prior to checking the fallback.
* This exception instance may have been generated via a number of mechanisms:
* 1) failed execution (in this case, same result as {@link #getFailedExecutionException()}.
* 2) timeout
* 3) short-circuit
* 4) rejection
* 5) bad request
*
* If the command execution was successful, then this exception instance is null (there was no exception)
*
* Note that the caller of the command may not receive this exception, as fallbacks may be served as a response to
* the exception.
*
* @return Throwable or null
*/
public Throwable getExecutionException() {
return executionResult.getExecutionException();
}
产生的异常有5种,分别是:
1)执行失败,非Hystrix引起的异常,此情况可以通过getFailedExecutionException获取;
2)超时,会返回HystrixTimeoutException
3)短路,返回RuntimeException
4)拒绝,返回RejectedExecutionException
5)请求异常,返回HystrixBadRequestException,表示参数或者状态错误。
另外,如果没有异常,则返回null。
getExecutionException与getFailedExecutionException的区别:
/** * Get the Throwable/Exception thrown that caused the failure. * <p> * If <code>isFailedExecution() == true</code> then this would represent the Exception thrown by the <code>run()</code> method. * <p> * If <code>isFailedExecution() == false</code> then this would return null. * * @return Throwable or null */ public Throwable getFailedExecutionException() { return executionResult.getException(); }
getFailedExecutionException仅仅返回执行失败的异常,getExecutionException返回所有的异常。
因此,我们可以通过这几个方法,区分异常的产生原因,包装成可读信息。
@Override
protected Object getFallback() {
Throwable executionException = super.getExecutionException();
if (executionException == null) throw new ProcessException("调用失败,未知错误");
//非Hystrix造成的异常
if (super.isFailedExecution()) {
if (executionException instanceof ProcessException) throw (ProcessException) executionException;
throw new ProcessException("调用失败: " + executionException.getMessage());
}
//Hystrix引起的异常
if (executionException instanceof HystrixTimeoutException) throw new ProcessException("hystrix调用超时");
if (executionException instanceof RejectedExecutionException) throw new ProcessException("hystrix触发限流");
if (executionException instanceof RuntimeException) throw new ProcessException("hystrix触发短路");
if (executionException instanceof HystrixBadRequestException) throw new ProcessException("hystrix请求失败");
throw new ProcessException("hystrix调用失败");
}