【Java】hystrix - @EnableCircuitBreaker那些事

hystrix - @EnableCircuitBreaker那些事

大军发布于 今天 12:30

@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代理我们的方法,熔断、限流,就是在这里开始的。
【Java】hystrix - @EnableCircuitBreaker那些事

java源码分析hystrix限流

阅读 41发布于 今天 12:30

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

大军

运气好的时候要拼命努力,运气不好的时候要储备能力

370 声望

29 粉丝

0 条评论

得票时间

avatar

大军

运气好的时候要拼命努力,运气不好的时候要储备能力

370 声望

29 粉丝

宣传栏

@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代理我们的方法,熔断、限流,就是在这里开始的。
【Java】hystrix - @EnableCircuitBreaker那些事

以上是 【Java】hystrix - @EnableCircuitBreaker那些事 的全部内容, 来源链接: utcz.com/a/108035.html

回到顶部