本着从源码入手学习工具的思想,以hystrixCommand.execute()方法为例,看了下hystrix的执行过程,说实话有点绕,而且Rxjava的一些语法规则了解的也不是很透,
只能以Rxjava 回调的思想说服自己去,最后执行是怎么样的,最后将执行defer()方法中的逻辑。
日常分享我感觉优秀的文章:
SpringCloud使用Hystrix实现断路器
降级熔断框架 Hystrix 源码解析:滑动窗口统计
那么回到hystrix的功能上:
- 资源隔离
- 熔断
- 降级
功能点理解
1资源隔离
在微服务下,防止链路中某一个点的阻塞,感染上游节点,对整个系统造成影响。
原理:
我的理解就是通过控制服务中可执行的线程数量
资源隔离的方式:
- 线程池
- 信号量
为什么都说是这两种,源码中给出答案:
/**
* Isolation strategy to use when executing a {@link HystrixCommand}.
* <p>
* <ul>
* <li>THREAD: Execute the {@link HystrixCommand#run()} method on a separate thread and restrict concurrent executions using the thread-pool size.</li>
* <li>SEMAPHORE: Execute the {@link HystrixCommand#run()} method on the calling thread and restrict concurrent executions using the semaphore permit count.</li>
* </ul>
*/
public static enum ExecutionIsolationStrategy {
THREAD, SEMAPHORE
}
那么这两这个方式有什么不一样呢,因为两者都设定了可执行线程的上限,如果我可执行方法是定的,那么我选择这两种方式最终效果有很大区别吗?看图说话:
1.看了代码,对信号量和线程池的「是否支持异步」这个仍感疑惑,看了些文章这块都是一笔带过,有研究过这块的同学,可以帮忙解惑下!
2.「是否支持超时」的区别呢,直接上代码,方便理解:
public class SemaphoreCommand extends HystrixCommand<String> {
public static HystrixCommand.Setter getSetterConfig(){
String commandName = "TestCommand";
HystrixCommand.Setter commandConfig = HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandName))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandName))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
.withExecutionTimeoutInMilliseconds(100));
return commandConfig;
}
protected SemaphoreCommand(Setter setter) {
super(setter);
}
@Override
protected String getFallback() {
System.out.println("Fallback in " + Thread.currentThread().getName());
return "Fallback from " + Thread.currentThread().getName();
}
@Override
protected String run() throws Exception {
System.out.println("RUN start in " + Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("RUN end in " + Thread.currentThread().getName());
return "HELLO from " + Thread.currentThread().getName();
}
public static void main(String[] args) {
SemaphoreCommand command = new SemaphoreCommand(getSetterConfig());
System.out.println(command.execute());
}
}
fallback之后,仍会等待run方法结束。超时设置无效。【这个返回结果是否可以是信号量同步的佐证呢?】
2 熔断和降级
这部分很多文章都分析到了。自己看了源码但是理解也不是很深,这部分就跳过,安慰自己:记住作用就好。
3 @EnableCircuitBreaker 注解的作用
@EnableCircuitBreaker annotation中使用了:
@Import(EnableCircuitBreakerImportSelector.class)
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector
extends SpringFactoryImportSelector<EnableCircuitBreaker> {
@Override
protected boolean isEnabled() {
return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled",
Boolean.class, Boolean.TRUE);
}
}
===================
@EnableAutoConfiguration
public @interface SpringBootApplication {
……
}
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
……
}
那么这个类最后作用就是和springboot自动加载引入jar一样,在spring容器中注入EnableCircuitBreaker配置的类:
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
这个类就解释了我们为什么可以在普通方法上使用@HystrixCommand注解,这个方法就具备了hystrix熔断相关的功能。