关于java:hystrix-EnableCircuitBreaker那些事

37次阅读

共计 3408 个字符,预计需要花费 9 分钟才能阅读完成。

@EnableCircuitBreaker

咱们应用 hystrix 的时候,都会在 application 上应用 @EnableCircuitBreaker 注解,咱们看看这个主键到底做了什么事件。
他 import 了 EnableCircuitBreakerImportSelector,看到 ImportSelector 咱们应该会联想到,他前面可能有某些 bean 会被注入到 IOC 容器中。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {}

咱们跟着看 EnableCircuitBreakerImportSelector,这里会有 isEnabled 办法,他的实现类 SpringFactoryImportSelector 我这里就不说了。他的意思是,如果返回 true 的时候,会从 spring.factories 中读取 org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker 对应的HystrixCircuitBreakerConfiguration,最初这个 HystrixCircuitBreakerConfiguration 就会被实例化。这个类被加载后,他会紧接着加载 HystrixCommandAspect,一看到 Aspect,就晓得 AOP 吧。咱们看看他用这个干吗。

public class EnableCircuitBreakerImportSelector
        extends SpringFactoryImportSelector<EnableCircuitBreaker> {
    @Override
    protected boolean isEnabled() {return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled",
                Boolean.class, Boolean.TRUE);
    }
}

HystrixCommandAspect

他这里定义了一个 @Pointcut,咱们平时用 hystrix 的时候,就是会加 HystrixCommand 吧,当初晓得为什么要加这个注解了吧,他会通过 AOP 拦挡代理相应办法。

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {}

HystrixCommand 注解有多个配置的参数,比方:

  • groupKey:命令分组键,能够依据这个分组,统计他的各个指标,默认类名。
  • commandKey:命令键,默认办法名。
  • threadPoolKey:线程池名,如果没有设置,默认为 groupKey。
  • fallbackMethod:服务降级调用的办法。
  • threadPoolProperties:配置线程池用的。

当然还有其余,就不一一列了。
上面咱们看看办法,这里次要是通过咱们配置的信息,生成一个 GenericCommand 对象,通过这个对象调用 execute 办法。

@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");
    }
    // 依据注解获取 CommandMetaHolderFactory 还是 CollapserMetaHolderFactory
    MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
    // 通过配置信息生成元数据
    MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
    // 创立 GenericCommand,会把元数据的信息赋值到 GenericCommand 的属性中。// 除此,线程池、commandActions 也是这里
    HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
    ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
            metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

    Object result;
    try {if (!metaHolder.isObservable()) {
            // 这里会把 GenericCommand 强制转为 HystrixExecutable,而后调用 execute 办法
            result = CommandExecutor.execute(invokable, executionType, metaHolder);
        } else {result = executeObservable(invokable, executionType, metaHolder);
        }
    } catch (HystrixBadRequestException e) {throw e.getCause();
    } catch (HystrixRuntimeException e) {throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
    }
    return result;
}

把 GenericCommand 转为 HystrixExecutable 对象。

public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
    // 其余略
    return castToExecutable(invokable, executionType).execute();
    // 其余略    
}

private static HystrixExecutable castToExecutable(HystrixInvokable invokable, ExecutionType executionType) {if (invokable instanceof HystrixExecutable) {return (HystrixExecutable) invokable;
    }
    // 其余略    
}

总结

@EnableCircuitBreaker 次要是为了加载 HystrixCircuitBreakerConfiguration 以及 HystrixCommandAspect,通过 AOP 代理咱们的办法,熔断、限流,就是在这里开始的。

正文完
 0