Hystrix 旨在經過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix具有擁有回退機制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監控和配置等功能。java
Dubbo是Alibaba開源的,目前國內最流行的java rpc框架。spring
本文介紹在spring應用裏,怎麼把Dubbo和Hystrix結合起來使用。緩存
spring boot官方提供了對hystrix的集成,直接在pom.xml里加入依賴:架構
1
2
3
4
5
|
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>
1.4
.
4
.RELEASE</version>
</dependency>
|
而後在Application類上增長@EnableHystrix
來啓用hystrix starter:框架
1
2
3
|
@SpringBootApplication
@EnableHystrix
public
class
ProviderApplication {
|
在Dubbo的Provider上增長@HystrixCommand
配置,這樣子調用就會通過Hystrix代理。async
1
2
3
4
5
6
7
8
9
10
11
12
|
@Service
(version =
"1.0.0"
)
public
class
HelloServiceImpl
implements
HelloService {
@HystrixCommand
(commandProperties = {
@HystrixProperty
(name =
"circuitBreaker.requestVolumeThreshold"
, value =
"10"
),
@HystrixProperty
(name =
"execution.isolation.thread.timeoutInMilliseconds"
, value =
"2000"
) })
@Override
public
String sayHello(String name) {
// System.out.println("async provider received: " + name);
// return "annotation: hello, " + name;
throw
new
RuntimeException(
"Exception to show hystrix enabled."
);
}
}
|
對於Consumer端,則能夠增長一層method調用,並在method上配置@HystrixCommand
。當調用出錯時,會走到fallbackMethod = "reliable"
的調用裏。分佈式
1
2
3
4
5
6
7
8
9
10
|
@Reference
(version =
"1.0.0"
)
private
HelloService demoService;
@HystrixCommand
(fallbackMethod =
"reliable"
)
public
String doSayHello(String name) {
return
demoService.sayHello(name);
}
public
String reliable(String name) {
return
"hystrix fallback value"
;
}
|
經過上面的配置,很簡單地就完成了Spring Boot裏Dubbo + Hystrix的集成。ide
傳統spring annotation應用的配置其實也很簡單,和spring boot應用不一樣的是:函數
@EnableAspectJAutoProxy
@Configuration
配置HystrixCommandAspect
Bean。
1
2
3
4
5
6
7
8
9
10
11
12
|
@Configuration
@EnableDubbo
(scanBasePackages =
"com.alibaba.dubbo.samples.annotation.action"
)
@PropertySource
(
"classpath:/spring/dubbo-consumer.properties"
)
@ComponentScan
(value = {
"com.alibaba.dubbo.samples.annotation.action"
})
@EnableAspectJAutoProxy
static
public
class
ConsumerConfiguration {
@Bean
public
HystrixCommandAspect hystrixCommandAspect() {
return
new
HystrixCommandAspect();
}
}
|
在上面的例子裏能夠看到,Hystrix對Spring的集成是經過Spring AOP來實現的。下面簡單分析下實現。源碼分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
@Aspect
public
class
HystrixCommandAspect {
@Pointcut
(
"@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)"
)
public
void
hystrixCommandAnnotationPointcut() {
}
@Pointcut
(
"@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)"
)
public
void
hystrixCollapserAnnotationPointcut() {
}
@Around
(
"hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()"
)
public
Object methodsAnnotatedWithHystrixCommand(
final
ProceedingJoinPoint joinPoint)
throws
Throwable {
Method method = getMethodFromTarget(joinPoint);
Validate.notNull(method,
"failed to get method from joinPoint: %s"
, joinPoint);
if
(method.isAnnotationPresent(HystrixCommand.
class
) && method.isAnnotationPresent(HystrixCollapser.
class
)) {
throw
new
IllegalStateException(
"method cannot be annotated with HystrixCommand and HystrixCollapser "
+
"annotations at the same time"
);
}
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
Object result;
try
{
if
(!metaHolder.isObservable()) {
result = CommandExecutor.execute(invokable, executionType, metaHolder);
}
else
{
result = executeObservable(invokable, executionType, metaHolder);
}
}
catch
(HystrixBadRequestException e) {
throw
e.getCause() !=
null
? e.getCause() : e;
}
catch
(HystrixRuntimeException e) {
throw
hystrixRuntimeExceptionToThrowable(metaHolder, e);
}
return
result;
}
|
HystrixCommandAspect
裏定義了兩個註解的AspectJ Pointcut:@HystrixCommand
, @HystrixCollapser
。全部帶這兩個註解的spring bean都會通過AOP處理@Around
AOP處理函數裏,能夠看到Hystrix會建立出HystrixInvokable
,再經過CommandExecutor
來執行@EnableHystrix
引入了@EnableCircuitBreaker
,@EnableCircuitBreaker
引入了EnableCircuitBreakerImportSelector
1
2
3
4
5
6
7
|
@EnableCircuitBreaker
public
@interface
EnableHystrix {
}
@Import
(EnableCircuitBreakerImportSelector.
class
)
public
@interface
EnableCircuitBreaker {
}
|
EnableCircuitBreakerImportSelector
繼承了SpringFactoryImportSelector<EnableCircuitBreaker>
,使spring加載META-INF/spring.factories
裏的EnableCircuitBreaker
聲明的配置在META-INF/spring.factories
裏能夠找到下面的配置,也就是引入了HystrixCircuitBreakerConfiguration
。
1
2
|
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
|
HystrixCircuitBreakerConfiguration
裏能夠發現建立了HystrixCommandAspect
1
2
3
4
5
6
7
|
@Configuration
public
class
HystrixCircuitBreakerConfiguration {
@Bean
public
HystrixCommandAspect hystrixCommandAspect() {
return
new
HystrixCommandAspect();
}
|
可見spring-cloud-starter-netflix-hystrix
實際上也是建立了HystrixCommandAspect
來集成Hystrix。
另外spring-cloud-starter-netflix-hystrix
裏還有metrics, health, dashboard等集成。
@Service
是一個spring bean,直接在上面配置@HystrixCommand
便可@Reference
,能夠經過加一層簡單的spring method包裝,配置@HystrixCommand
便可HystrixCommandAspect
來集成Spring AOP,配置了@HystrixCommand
和@HystrixCollapser
的spring method都會被Hystrix處理歡迎學Java和大數據的朋友們加入java架構交流: 855835163
加羣連接:jq.qq.com/?_wv=1027&a…
羣內提供免費的架構資料還有:Java工程化、高性能及分佈式、高性能、深刻淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的免費直播講解 能夠進來一塊兒學習交流哦
直播課堂地址:ke.qq.com/course/2602…