一、基本概念
Hystrix把一个分布式系统的某一个服务打造成一个高可用的服务最重要的手段之一就是对资源隔离,即通过限流来限制对某一服务的访问量,比如说对mysql的访问,为了避免过大的流量直接请求mysql服务,hystrix通过线程池或者信号量技术进行限流访问。
在《Hystrix-基本概念》中,我们了解到Hystrix的两种隔离技术:线程池和信号量。也分析了在什么样的场景下使用线程池和信号量,通常来说线程池资源隔离技术一般用于对依赖服务的网络请求访问,需要解决timeout问题。信号量则适合对内部的一些比较复杂的业务逻辑访问,不涉及任何的网络请求,当并发量超过计数器指定值时,直接拒绝。
线程池隔离的最大优点在于:任何一个依赖服务都可以被隔离在自己的线程池内,即使自己的线程池资源填满了,也不会影响任何其他的服务调用。最大缺点在于:增加了cpu的开销,除了tomcat本身的调用线程之外,还有hystrix自己管理的线程池。每个command的执行都依托一个独立的线程,会进行排队,调度,还有上下文切换。
二、限流实验
1、创建command
public class CommandReject extends HystrixCommand<String> {
private String tag;
public CommandReject(String tag) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandReject"))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()//
.withCoreSize(5)// 设置线程池大小
.withMaxQueueSize(2))// 设置最大等待队列大小
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()//
.withExecutionTimeoutInMilliseconds(3000)));// 设置timeout时长,默认1000,一个command运行超出这个时间,就被认为是timeout
this.tag = tag;
}
@Override
protected String run() throws Exception {
// command的执行等待1s
Thread.sleep(1000);
return tag;
}
@Override
protected String getFallback() {
return "降级处理";
}
}
2、执行command
public class CommandRejectTest {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10; i++) {
new TestThread(i).start();
}
}
private static class TestThread extends Thread {
private int index;
public TestThread(int index) {
this.index = index;
}
@Override
public void run() {
CommandReject breaker = new CommandReject("success");
System.out.println("第" + (index + 1) + "次请求,结果为:" + breaker.execute());
}
}
}
3、执行结果
我们设置了线程池的大小为5,然后最大等待队列的大小为2,同时设置了timeout时长为3000毫秒,这是为了避免command执行发生timeout。然后我们模拟了10个并发量,那么理论上来说有7个是正常执行,3个应该是直接被限流走fallback降级处理。而实验的结果也刚好符合我们的预期。