在HystrixCommand實現的run()方法中拋出異常時,除了HystrixBadRequestException以外,其餘異常均會被Hystrix認爲命令執行失敗並觸發服務降級的處理邏輯,因此當須要在命令執行中拋出不觸發服務降級的異常時來選擇它。java
在使用註解配置實現Hystrix命令時,能夠忽略指定的異常類型,只須要經過設置@HystrixCommand註解的ignoreExceptions參數,以下:git
@HystrixCommand(fallbackMethod = "getDefaultUser", ignoreExceptions = NullPointerException.class) public User findUserById(Long id) { return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id); }
當上述方法拋出NullPointerException的異常時,不會觸發後續的fallback邏輯。github
在傳統的繼承實現Hystrix命令時,能夠在getFallback()方法中經過getExecutionException()方法來獲取具體的異常,而後經過判斷來進入不一樣的處理邏輯。spring
在註解配置方式中,只須要在fallback實現方法的參數中增長Throwable e對象的定義,這樣在方法內部就能夠獲取觸發服務降級的具體異常內容。函數
public UserCommand(RestTemplate restTemplate, Long id) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GroupName")).andCommandKey(HystrixCommandKey.Factory.asKey("CommandName"))); this.restTemplate = restTemplate; this.id = id; }
從上面的代碼中能夠看出,咱們並無直接設置命令名稱,而是先調用了withGroupKey來設置命令組名,而後才經過調用andCommandKey來設置命令名。this
在Setter中只有withGroupKey靜態函數能夠建立Setter的實例,所以GroupKey是每一個Setter必須的參數,而CommandKey則是一個可選參數。線程
經過設置命令組,Hystrix會根據組來組織和統計命令的告警、儀表盤等信息。除了上述能夠統計信息以外,Hystrix命令默認的線程劃分也是根據命令分組來實現的。默認狀況下,Hystrix會讓相同組名的命令使用同一個線程池,因此咱們須要在建立Hystrix命令時爲其指定命令組名來實現默認的線程池劃分。rest
Hystrix還提供HystrixThreadPoolKey來對線程池進行設置,經過它能夠實現更細粒度的線程池劃分。code
public UserCommand(RestTemplate restTemplate, Long id) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GroupName")) .andCommandKey(HystrixCommandKey.Factory.asKey("CommandName")) .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("ThreadPoolKey"))); this.restTemplate = restTemplate; this.id = id; }
在沒有指定HystrixThreadPoolKey的狀況下,會使用命令組的方式來劃分線程池。一般狀況下,咱們儘可能使用HystrixThreadPoolKey來指定線程池的劃分。由於多個不一樣的命令可能從業務邏輯上來看屬於同一個組,可是每每從實現自己上須要跟其餘命令來進行隔離。對象
使用註解時只須要設置註解的commandKey、groupKey以及threadPoolKey屬性便可,他分別表示了命令名稱、分組以及線程池劃分。
@HystrixCommand(fallbackMethod = "getDefaultUser", ignoreExceptions = NullPointerException.class, commandKey = "findUserById", groupKey = "UserGroup", threadPoolKey = "findUserByIdThread") public User findUserById(Long id) { return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id); }