在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); }