1.0 Hystrix的作用
- 进行服务的隔离及熔断处理
- 优雅的降级处理
- 缓存:提供了请求缓存、请求合并、支持实时监控
1.1 Hystrix项目搭建
1.1.1 依赖相关jar
// 新增hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1.1.2 Hystrix相关配置
使用FeignClient作为远程调用,只需要配置feign结合的ribbon超时时间,以及其他关于熔断的配置即可。
spring:
application:
name: loy-hystrix
server:
port: 9092
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9081/eureka/
fetchRegistry: true
instance:
instanceId: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
preferIpAddress: true
feign:
client:
config:
default:
connect-timeout: 1000
read-timeout: 2000
#feign熔断器开关
hystrix:
enabled: true
正常情况下不会进入fallback方法,此处当超时时,会进行fallback方法,进行熔断处理的返回。这里配置的超时时间为1s,只要调整被调用的服务端的睡眠时间即可模拟。
此处调用的方法为:http://localhost:9092/hystrix-feign-test
正常返回结果为:
熔断后返回结果为:
1.2 Hystrix源码分析
1.2.1 源码入口分析
(1) 找到对用的自动配置类 HystrixCircuitBreakerConfiguration
(2) 解析HystrixCommandAspect
1)初始化一个切面Bean
// 创建一个切面类
@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}
2)拦截@HystrixCommand注解
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
3) 在切面的执行方法中进行HystrixCommand的run方法执行
// 判断metaHolder是否开启观察者模式
if (!metaHolder.isObservable()) {
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
// 进行方法的执行
switch (executionType) {
// 同步方式执行,直接调用command的run方法
case SYNCHRONOUS: {
return castToExecutable(invokable, executionType).execute();
}
// 异步方式执行,开启future
case ASYNCHRONOUS: {
HystrixExecutable executable = castToExecutable(invokable, executionType);
if (metaHolder.hasFallbackMethodCommand()
&& ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {
return new FutureDecorator(executable.queue());
}
return executable.queue();
}
// 观察者模式执行
case OBSERVABLE: {
HystrixObservable observable = castToObservable(invokable);
return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();
}
default:
throw new RuntimeException("unsupported execution type: " + executionType);
}
1.3 Hystrix的四种调用方式
1.3.1 observe()方式 - 观察方式(订阅方式)
事件注册前进行调用方式
(1)第一步是事件注册前,先调用observe()自动触发执行run()。(如果继承的是HystrixCommand,hystrix将创建新线程非堵塞执行run();如果继承的是HystrixObservableCommand,将以调用程序线程堵塞执行construct())
(2)第二步是从observe()返回后调用程序调用subscribe()完成事件注册,如果run()/construct()执行成功则触发onNext()和onCompleted(),如果执行异常则触发fallback()方法。
1.3.2 toObservable()方式 -被观察者方式
事件注册后进行调用方式
(1)第一步是事件注册前,调用toObservable()就直接返回一个Observable<String>对象
(2)第二步调用subscribe()完成事件注册后自动触发执行run()/construct()(如果继承的是HystrixCommand,hystrix将创建新线程非堵塞执行run(),调用程序不必等待run();如果继承的是HystrixObservableCommand,将以调用程序线程堵塞执行construct(),调用程序等待construct()执行完才能继续往下走),如果run()/construct()执行成功则触发onNext()和onCompleted(),如果执行异常则触发fallback()方法。
1.3.3 execute()方式
以同步堵塞方式执行run()。调用execute()后,hystrix先创建一个新线程运行run(),接着调用程序要在execute()调用处一直堵塞着,直到run()运行完成。
1.3.4 queue()方式
以异步非堵塞方式执行run()。调用queue()就直接返回一个Future对象,同时hystrix创建一个新线程运行run(),调用程序通过Future.get()拿到run()的返回结果,而Future.get()是堵塞执行的。