HystrixCommand : 用在依赖的服务返回单个操作结果的时候
HystrixObservableCommand:用在依赖的服务返回多个操作结果的时候,调用Observable.from
可以传入多个命令,返回多条结果
如果于命令相关的线程池和请求队列,或者信号量(不使用线程池的时候)已经占满,那么hystrix也不会执行命令
这里hystrix 所判断的线程池并非容器的线程池,而是每个依赖服务的专有线程池
hystrix 使用舱壁模式实现线程池的隔离,它会为一个依赖服务创建一个独立的线程池,这样就算某个依赖服务出现延迟过高的情况,也只是对该依赖服务的调用产生影响,而不会拖慢其他的依赖服务
hystrix会将“成功”,“失败”,“超时”等信息报告给断路器,而断路器会维护一组计数器来统计这些数据
断路器会使用这些统计数据来决定是否要将断路器打开,来对某个依赖服务的请求进行“熔断/断路”,直到恢复
fallback 处理
当命令执行失败的时候,hystrix会进入fallback尝试回退处理,我们通常也称该操作为"服务降级"。而能够引起服务降级处理可能有
a 当命令处于“熔断/短路”状态,断路器是打开的时候
b 当前命令的线程池,请求队列或者信号量被占满的时候
c hystrixObservableCommand.construct或hystrixcommand.run() 抛出异常的时候
如果降级执行发现失败的时候,hystrix会根据不同的执行方法做出不同的处理
a execute() 抛出异常
b queue() 正常返回future 对象,但是当调用get()来获取结果的时候会抛出异常
c observe() 正常返回observable对象,当订阅它的时候,将立即通过调用订阅的onError()方法来通知中止请求
d toObservable() 正常返回Observable对象,当订阅它的时候,将通过调用订阅者的onError方法来通知中止请求
版本 spring boot 1.5.14
异常传播
在HystrixCommand实现run()方法中抛出异常时,除了HystrixBadRequestException之外,其他异常均会被hystrix认为命令执行失败并触发服务降级的处理逻辑,通过设置HystrixCommand 注解的ignoreExceptions 参数,可以忽略指定异常类型功能
@HystrixCommand(fallbackMethod = "helloFallback",ignoreExceptions = {NumberFormatException.class})
public String helloService(){
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
如上,当方法跑出了类型为NumberFormatException的异常时,hystrix会将它包装在HystrixBadRequestException中抛出,
这样就不会触发后续的fallback逻辑
异常获取
只需要在fallback实现方法的参数中增加Throwable e 对象的定义,这样在方法内部就可以获取触发服务降级的具体异常内容了
public String helloFallback(Throwable e){
return "error:"+e.getMessage();
}
命令名称,分组以及线程池划分
hystrix 会根据组来组织和统计命令的告警,仪表盘等信息。
如果没有特别指定threadPoolKey的情况下,会使用命令组的方式来划分线程池。
@HystrixCommand(commandKey = "helloService",
groupKey = "hellogroup",
threadPoolKey = "hellothread",
fallbackMethod = "helloFallback",
ignoreExceptions = {HystrixBadRequestException.class})
public String helloService(){
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
请求缓存
hystrix 会根据 调用依赖服务,传入的key是否相同,而决定是否使用缓存,假如调用方调用了
getUserById(long key),key 为1 ,那么会先去看是否有该key为一的缓存,有则返回,
没有则调用请求,这样就可以减少重复的请求数,降低依赖服务的并发度
/* 由于该方法被@CacheResult注解修改,所以hystrix会将该结果置入请求缓存中,而它的缓存Key 值会使用所以的参数,也就是这里Long类型的id值 */ @CacheResult @HystrixCommand public User getUserById(Long id){ return restTemplate.getForObject("http://USER-SERVICE/users/{1}",User.class,id); } |
/* 指定缓存key */ @CacheResult(cacheKeyMethod = "getUserByIdCacheKey") @HystrixCommand public User getUserById(Long id){ return restTemplate.getForObject("http://USER-SERVICE/users/{1}",User.class,id); }
private Long getUserByIdCacheKey(Long id){ return id; } |
/* 指定缓存key ,优先级比cacheKeyMethod 低 */ @CacheResult @HystrixCommand public User getUserById(@CacheKey("id") Long id){ return restTemplate.getForObject("http://USER-SERVICE/users/{1}",User.class,id); } |
/* 缓存清理 当我们通过@CacheResult注解将请求结果置入hystrix的请求缓存之中,若该内容调用了更新操作,那么此时请求 缓存中的结果与实际结果会产生不一致,所有我们需要在更新操作上对失效的缓存进行清理 */ @CacheRemove(commandKey = "getUserById") @HystrixCommand public void update(@CacheKey("id") User user){ restTemplate.postForObject("http://USER-SERVICE/users/{1}",user,User.class); } |
请求合并
在高并发的情况下,因通信次数的增加,总的通信时间消耗将会变得不那么理想。请求合并,可以将一定时间内的请求,合并起来,发起一个批量请求。例如 一定时间内所有的请求都是 查询单个用户 假设为
getUserById(String key),那么请求合并即将所有请求合并为一个批量查询 假如为getUserBatch(List<Long> ids),前提是服务提供方要提供该方法
@Autowired RestTemplate restTemplate;
@HystrixCollapser(batchMethod = "findAll",collapserProperties = { @HystrixProperty(name = "timerDelayInMilliseconds",value = "100") }) public User find(Long id){ return null; }
@HystrixCommand public java.util.List<User> findAll(java.util.List<Long> ids){ return restTemplate.getForObject("http://USER-SERVICE/users?ids={1}" ,java.util.List.class, StringUtils.join(ids,",")); } |
属性
public class HystrixCommandConfiguration 记录了hystrix 基本的属性
如 command属性 execution配置
HystrixCommandExecutionConfig
private final int semaphoreMaxConcurrentRequests; //执行隔离策略 private final HystrixCommandProperties.ExecutionIsolationStrategy isolationStrategy; //超时 时是否打断 private final boolean threadInterruptOnTimeout; private final String threadPoolKeyOverride; //是否启用超时时间 private final boolean timeoutEnabled; //配置hystrixcommand的超时时间 private final int timeoutInMilliseconds; private final boolean fallbackEnabled; private final int fallbackMaxConcurrentRequest; private final boolean requestCacheEnabled; private final boolean requestLogEnabled; |
参考 spring cloud微服务实战