異常的傳播和捕獲
傳播:在HystrixCommand實現的run()方法中跑出異常時,除了HystrixBadRequestException之外,其他異常均會被Hystrix認為命令執行失敗並處罰服務降級的處理邏輯。下面的例子通過@HystrixCommand注解的ignoreException參數來設置。
捕獲:我們可以在降級方法中添加Throwable參數來捕獲異常。
package org.hope.hystrix.example.exception; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.stereotype.Service; @Service public class HystrixHandleException { /** * 當設置ignoreExceptions參數時, * 拋出對應的異常就不會觸發降級(也就是不會調用failMethod()方法). */ @HystrixCommand( ignoreExceptions = {NullPointerException.class, ArithmeticException.class}, fallbackMethod = "failMethod" ) public String getUserName(Long id) { Long re = id/0; //會拋ArithmeticException String param = null; param.trim(); // 此處會拋NullPointException return "張三"; } private String failMethod(Long id, Throwable e) { return e.getMessage(); } }
單元測試:
package org.hope.hystrix.example.exception; import org.hope.hystrix.example.HystrixApplication; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = HystrixApplication.class) public class HystrixHandleExceptionTest { @Autowired private HystrixHandleException hystrixHandleException; @Test public void test() { String name = hystrixHandleException.getUserName(10L); System.out.println("==================" + name); } }
運行結果
java.lang.ArithmeticException: / by zero
at org.hope.hystrix.example.exception.HystrixHandleException.getUserName(HystrixHandleException.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.netflix.hystrix.contrib.javanica.command.MethodExecutionAction.execute(MethodExecutionAction.java:116)
at com.netflix.hystrix.contrib.javanica.command.MethodExecutionAction.executeWithArgs(MethodExecutionAction.java:93)
at com.netflix.hystrix.contrib.javanica.command.MethodExecutionAction.execute(MethodExecutionAction.java:78)
at com.netflix.hystrix.contrib.javanica.command.GenericCommand$1.execute(GenericCommand.java:48)
at com.netflix.hystrix.contrib.javanica.command.AbstractHystrixCommand.process(AbstractHystrixCommand.java:145)
at com.netflix.hystrix.contrib.javanica.command.GenericCommand.run(GenericCommand.java:45)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
參考:
[1]Github,https://github.com/Netflix/Hystrix/wiki/How-it-Works
[2] 《SpringCloud微服務實戰》,電子工業出版社,翟永超
