美文网首页扣丁学堂Java培训Java 杂谈
扣丁学堂Java开发SpringBoot中如何使用断路器详解

扣丁学堂Java开发SpringBoot中如何使用断路器详解

作者: 994d14631d16 | 来源:发表于2018-08-27 10:06 被阅读0次

      在现如今,随着互联网技术飞速的发展和进步,越来越来多程序员使用Spring进行开发,Spring也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring的边界不断的进行扩充,到了后来Spring几乎可以做任何事情了,市面上主流的开源软件、中间件都有Spring对应组件支持,人们在享用Spring的这种便利之后,也遇到了一些问题。

    ​  断路器本身是电路上的一种过载保护装置,当线路中有电器发生短路时,它能够及时的切断故障电路以防止严重后果发生。通过服务熔断(也可以称为断路)、降级、限流(隔离)、异步RPC等手段控制依赖服务的延迟与失败,防止整个服务雪崩。一个断路器可以装饰并且检测了一个受保护的功能调用。根据当前的状态决定调用时被执行还是回退。通常情况下,一个断路器实现三种类型的状态:open、half-open以及closed:

      closed状态的调用被执行,事务度量被存储,这些度量是实现一个健康策略所必备的。

      倘若系统健康状况变差,断路器就处在open状态。此种状态下,所有调用会被立即回退并且不会产生新的调用。open状态的目的是给服务器端回复和处理问题的时间。

      一旦断路器进入一个open状态,超时计时器开始计时。如果计时器超时,断路器切换到half-open状态。在half-open状态调用间歇性执行以确定问题是否已解决。如果解决,状态切换回closed状态。

      断路器背后的基本思想非常简单。将受保护的函数调用包装在断路器对象中,该对象监视故障。一旦故障达到某个阈值,断路器就会跳闸,并且所有对断路器的进一步调用都会返回错误,而根本不会进行受保护的呼叫。通常,如果断路器跳闸,您还需要某种监控器警报。

      如何快速使用Hystrix呢?

      1、加入@EnableCircuitBreaker注解

      @EnableCircuitBreaker

      @SpringBootApplication

      @EnableEurekaClient

      @EnableFeignClientspublicclassDroolsAppApplication{

      publicstaticvoidmain(String[]args){

      SpringApplication.run(DroolsAppApplication.class,args);

      }

      }

      Hystrix整体执行过程,首先,Command会调用run方法,如果run方法超时或者抛出异常,且启用了降级处理,则调用getFallback方法进行降级;

      2、使用@HystrixCommand注解

      @HystrixCommand(fallbackMethod="reliable")

      publicStringreadingList(){

      for(inti=0;i<10;i++){

      try{

      Thread.sleep(1000);

      }catch(InterruptedExceptione){

      e.printStackTrace();

      }

      }

      return"jinpingmei";

      }

      publicStringreliable(){

      return"youloveinterestingbook";

      }

      3、添加引用

      compile("org.springframework.cloud:spring-cloud-starter-hystrix")

      compile('org.springframework.cloud:spring-cloud-starter-turbine')

      4、设置超时时间

      hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

      执行结果如下:

      正常应该返回:

      你不要喜欢jinpingmei,要喜欢有意思的书;这样使用好舒服啊,@EnableCircuitBreaker这个注解就这么强大吗?

      HystrixCommandAspect通过AOP拦截所有的@HystrixCommand注解的方法,从而使得@HystrixCommand能够集成到Springboot中,

      HystrixCommandAspect的关键代码如下:

      1.方法hystrixCommandAnnotationPointcut()定义拦截注解HystrixCommand

      2.方法hystrixCollapserAnnotationPointcut()定义拦截注解HystrixCollapser

      3.方法methodsAnnotatedWithHystrixCommand(…)通过@Around(…)拦截所有HystrixCommand和HystrixCollapser注解的方法。详细见方法注解

      @Aspect

      publicclassHystrixCommandAspect{

      privatestaticfinalMapMETA_HOLDER_FACTORY_MAP;

      static{

      META_HOLDER_FACTORY_MAP=ImmutableMap.builder()

      .put(HystrixPointcutType.COMMAND,newCommandMetaHolderFactory())

      .put(HystrixPointcutType.COLLAPSER,newCollapserMetaHolderFactory())

      .build();

      }

      @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")

      publicvoidhystrixCommandAnnotationPointcut(){

      }

      @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")

      publicvoidhystrixCollapserAnnotationPointcut(){

      }

      @Around("hystrixCommandAnnotationPointcut()||hystrixCollapserAnnotationPointcut()")

      publicObjectmethodsAnnotatedWithHystrixCommand(finalProceedingJoinPointjoinPoint)throwsThrowable{

      Methodmethod=getMethodFromTarget(joinPoint);

      Validate.notNull(method,"failedtogetmethodfromjoinPoint:%s",joinPoint);

      if(method.isAnnotationPresent(HystrixCommand.class)&&method.isAnnotationPresent(HystrixCollapser.class)){

      thrownewIllegalStateException("methodcannotbeannotatedwithHystrixCommandandHystrixCollapser"+

      "annotationsatthesametime");

      }

      MetaHolderFactorymetaHolderFactory=META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));

      MetaHoldermetaHolder=metaHolderFactory.create(joinPoint);

      HystrixInvokableinvokable=HystrixCommandFactory.getInstance().create(metaHolder);

      ExecutionTypeexecutionType=metaHolder.isCollapserAnnotationPresent()?

      metaHolder.getCollapserExecutionType():metaHolder.getExecutionType();

      Objectresult;

      try{

      result=CommandExecutor.execute(invokable,executionType,metaHolder);

      }catch(HystrixBadRequestExceptione){

      throwe.getCause();

      }

      returnresult;

      }

      那么HystrixCommandAspect是如何初始化,是通过HystrixCircuitBreakerConfiguration实现的

      @Configuration

      publicclassHystrixCircuitBreakerConfiguration{

      @Bean

      publicHystrixCommandAspecthystrixCommandAspect(){

      returnnewHystrixCommandAspect();

      }

      那么谁来触发HystrixCircuitBreakerConfiguration执行初始化

      先看spring-cloud-netflix-core**.jar包的spring.factories里有这段配置,是由注解EnableCircuitBreaker触发

      org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\

      org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

      那么@EnableCircuitBreaker如何触发HystrixCircuitBreakerConfiguration

      通过源码查看,此类通过@Import初始化EnableCircuitBreakerImportSelector类

      @Target(ElementType.TYPE)

      @Retention(RetentionPolicy.RUNTIME)

      @Documented

      @Inherited

      @Import(EnableCircuitBreakerImportSelector.class)

      public@interfaceEnableCircuitBreaker{

      }

      EnableCircuitBreakerImportSelector是SpringFactoryImportSelector子类。此类在初始化后,会执行selectImports(AnnotationMetadatametadata)的方法。此方法会根据注解启动的注解(这里指@EnableCircuitBreaker)从spring.factories文件中获取其配置需要初始化@Configuration类(这里是org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration),从而最终初始化HystrixCommandAspect类,从而实现拦截HystrixCommand的功能

      以上就是通过@EnableCircuitBreake可以开启Hystrix的原理。Hystrix用到了观察者模式AbstractCommand.executeCommandAndObserve()模式,希望对大家的学习有所帮助,谢谢大家对扣丁学堂的支持。

    相关文章

      网友评论

        本文标题:扣丁学堂Java开发SpringBoot中如何使用断路器详解

        本文链接:https://www.haomeiwen.com/subject/dwlziftx.html