2019獨角獸企業重金招聘Python工程師標準>>> 
背景
Hystrix 旨在通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix具備擁有回退機制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監控和配置等功能。
Dubbo是Alibaba開源的,目前國內最流行的java rpc框架。
本文介紹在spring應用里,怎么把Dubbo和Hystrix結合起來使用。
Spring Boot應用
生成dubbo集成spring boot的應用
?
配置spring-cloud-starter-netflix-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 { |
配置Provider端
在Dubbo的Provider上增加@HystrixCommand
配置,這樣子調用就會經過Hystrix代理。
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端
對于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的集成。
傳統Spring Annotation應用
Demo地址
傳統spring annotation應用的配置其實也很簡單,和spring boot應用不同的是:
- 顯式配置Spring AOP支持:
@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 AOP原理
在上面的例子里可以看到,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
來執行
spring-cloud-starter-netflix-hystrix的代碼分析
@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等集成。
總結
- 對于dubbo provider的
@Service
是一個spring bean,直接在上面配置@HystrixCommand
即可 - 對于dubbo consumer的
@Reference
,可以通過加一層簡單的spring method包裝,配置@HystrixCommand
即可 - Hystrix本身提供
HystrixCommandAspect
來集成Spring AOP,配置了@HystrixCommand
和@HystrixCollapser
的spring method都會被Hystrix處理
歡迎學Java和大數據的朋友們加入java架構交流: 855835163
加群鏈接:https://jq.qq.com/?_wv=1027&k=5dPqXGI
群內提供免費的架構資料還有:Java工程化、高性能及分布式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階干貨的免費直播講解 ?可以進來一起學習交流哦
直播課堂地址:https://ke.qq.com/course/260263?flowToken=1007014