Hystrix是如何处理请求,在官网有详细介绍:https://github.com/Netflix/Hystrix/wiki/How-it-Works, 本文重点围绕下方流程图介绍一下主要的流程;
Hystrix是将我们的系统间调用包装成一个个Comman来执行,举个简单的例子:
public class TestCommand extends HystrixCommand<Integer> {
private TestServiceA serviceA;
private int index;
private static HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
//至少有10个请求,熔断器才进行错误率的计算
.withCircuitBreakerRequestVolumeThreshold(3)
//熔断器中断请求5秒后会进入半打开状态,放部分流量过去重试
.withCircuitBreakerSleepWindowInMilliseconds(5000)
//错误率达到50开启熔断保护
// .withCircuitBreakerErrorThresholdPercentage(30)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(2)
.withExecutionTimeoutEnabled(true)
.withExecutionTimeoutInMilliseconds(1000);
protected TestCommand(TestServiceA serviceA, int index) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("testGroupKey"))
.andCommandKey(HystrixCommandKey.Factory.asKey("testCommandKey"))
.andCommandPropertiesDefaults(setter)
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10)));
this.serviceA = serviceA;
this.index = index;
}
@Override
protected Integer run() throws Exception {
return serviceA.service(index);
}
@Override
protected Integer getFallback() {
// if service execute fail, do sth
return -1;
}
}
下面解释流程图中具体逻辑;
1、包装请求:
可以使用继承HystrixCommand或HystrixObservableCommand来包装业务方法;
2、发起请求:
使用调用Command的execute来执行一个业务方法调用;
Hystrix除了提供了execute方法,另外还提供了3种方来,所有的请求入口:
1 2 3 4 |
|
如上图所示:
执行同步调用execute方法,会调用queue().get()方法,queue()又会调用toObservable().toBlocking().toFuture();
所以,所有的方法调用都依赖Observable的方法调用,只是取决于是需要同步还是异步调用;
3、缓存处理:
当请求来到后,会判断请求是否启用了缓存(默认是启用的),再判断当前请求是否携带了缓存Key;
如果命中缓存就直接返回;否则进入剩下的逻辑;
4、判断断路器是否打开(熔断):
断路器是Hystrix的设计核心,断路器是实现快速失败的重要手段(断路器打开就直接返回失败);
可以设置断路器打开一定时间后,可以进行尝试进行业务请求(默认是5000毫秒);
5、判断是否进行业务请求(请求是否需要隔离或降级):
是否进行业务请求之前还会根据当前服务处理质量,判断是否需要去请求业务服务;
如果当前服务质量较低(线程池/队列/信号量已满),那么也会直接失败;
线程池或信号量的选择(默认是线程池):
线程池主要优势是客户端隔离和超时设置,但是如果是海量低延迟请求时,频繁的线程切换带来的损耗也是很可观的,这种情况我们就可以使用信号量的策略;
信号量的主要缺点就是不能处理超时,请求发送到客户端后,如果被客户端pending住,那么就需要一直等待;
6、执行业务请求:
当前服务质量较好,那么就会提交请求到业务服务器去;
HystrixObservableCommand.construct()
or HystrixCommand.run()
7、健康监测:
根据历史的业务方法执行结果,来统计当前的服务健康指标,为断路器是否熔断等动作作为依据;