Spring Boot中使用斷路器

           斷路器自己是電路上的一種過載保護裝置,當線路中有電器發生短路時,它可以及時的切斷故障電路以防止嚴重後果發生。經過服務熔斷(也能夠稱爲斷路)、降級、限流(隔離)、異步RPC等手段控制依賴服務的延遲與失敗,防止整個服務雪崩。一個斷路器能夠裝飾而且檢測了一個受保護的功能調用。根據當前的狀態決定調用時被執行仍是回退。一般狀況下,一個斷路器實現三種類型的狀態:open、half-open以及closed:java

  1. closed狀態的調用被執行,事務度量被存儲,這些度量是實現一個健康策略所必備的。
  2. 假若系統健康情況變差,斷路器就處在open狀態。此種狀態下,全部調用會被當即回退而且不會產生新的調用。open狀態的目的是給服務器端回覆和處理問題的時間。
  3. 一旦斷路器進入一個open狀態,超時計時器開始計時。若是計時器超時,斷路器切換到half-open狀態。在half-open狀態調用間歇性執行以肯定問題是否已解決。若是解決,狀態切換回closed狀態。

         斷路器背後的基本思想很是簡單。將受保護的函數調用包裝在斷路器對象中,該對象監視故障。一旦故障達到某個閾值,斷路器就會跳閘,而且全部對斷路器的進一步調用都會返回錯誤,而根本不會進行受保護的呼叫。一般,若是斷路器跳閘,您還須要某種監控器警報。spring

 如何快速使用Hystrix呢?下面跟着我1234……服務器

一、加入@EnableCircuitBreaker註解異步

@EnableCircuitBreaker
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClientspublic class DroolsAppApplication {
    public static void main(String[] args) {
        SpringApplication.run(DroolsAppApplication.class, args);
    }
}

Hystrix總體執行過程,首先,Command會調用run方法,若是run方法超時或者拋出異常,且啓用了降級處理,則調用getFallback方法進行降級;函數

二、使用@HystrixCommand註解ui

 @HystrixCommand(fallbackMethod = "reliable")
    public String readingList() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "jinpingmei";
    }

    public String reliable() {
        return "you love interesting book";
    }

三、添加引用spa

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

四、設置超時時間.net

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

     執行結果以下:3d

    正常應該返回:rest

你不要喜歡jinpingmei,要喜歡有意思的書;這樣使用好舒服啊,@EnableCircuitBreaker這個註解就這麼強大嗎?

HystrixCommandAspect 經過AOP攔截全部的@HystrixCommand註解的方法,從而使得@HystrixCommand可以集成到Spring boot中,

HystrixCommandAspect的關鍵代碼以下:

1.方法 hystrixCommandAnnotationPointcut() 定義攔截註解HystrixCommand

 2.方法 hystrixCollapserAnnotationPointcut()定義攔截註解HystrixCollapser

 3.方法methodsAnnotatedWithHystrixCommand(…)經過@Around(…)攔截全部HystrixCommand和HystrixCollapser註解的方法。詳細見方法註解

@Aspect
public class HystrixCommandAspect {

private static final Map<HystrixPointcutType, MetaHolderFactory> META_HOLDER_FACTORY_MAP;

static {
META_HOLDER_FACTORY_MAP = ImmutableMap.<HystrixPointcutType, MetaHolderFactory>builder()
.put(HystrixPointcutType.COMMAND, new CommandMetaHolderFactory())
.put(HystrixPointcutType.COLLAPSER, new CollapserMetaHolderFactory())
.build();
}

@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 {
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} catch (HystrixBadRequestException e) {
throw e.getCause();
}
return result;
}

那麼HystrixCommandAspect是如何初始化,是經過HystrixCircuitBreakerConfiguration實現的

@Configuration
public class HystrixCircuitBreakerConfiguration {

@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}

那麼誰來觸發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 @interface EnableCircuitBreaker {
}

          EnableCircuitBreakerImportSelector是SpringFactoryImportSelector子類。此類在初始化後,會執行selectImports(AnnotationMetadata metadata)的方法。此方法會根據註解啓動的註解(這裏指@EnableCircuitBreaker)從spring.factories文件中獲取其配置須要初始化@Configuration類(這裏是org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration),從而最終初始化HystrixCommandAspect 類,從而實現攔截HystrixCommand的功能

          以上就是經過@EnableCircuitBreake能夠開啓Hystrix的原理。Hystrix用到了觀察者模式AbstractCommand.executeCommandAndObserve()模式,下次咱們來深刻說一下觀察者模式。歡迎拍磚!

相關文章
相關標籤/搜索