赞
踩
我们在Spring Cloud项目中使用Hystrix时,引入相应的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
然后在启动类上添加@EnableCircuitBreaker注解,就可以使用Hystrix实现熔断降级了。这一切是如何实现的呢?我们来看这个注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {
}
继续看EnableCircuitBreakerImportSelector
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector
extends SpringFactoryImportSelector<EnableCircuitBreaker> {
@Override
protected boolean isEnabled() {
return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled",
Boolean.class, Boolean.TRUE);
}
}
EnableCircuitBreakerImportSelector继承了SpringFactoryImportSelector,传入的泛型EnableCircuitBreaker的全限定名会作为Key在spring.factories文件中查找对应的配置类,然后注入到IOC容器中。
下面是spring-cloud-netflix-hystrix-2.1.3.RELEASE.jar包中的spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.hystrix.HystrixAutoConfiguration,\
org.springframework.cloud.netflix.hystrix.security.HystrixSecurityAutoConfiguration
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
这里会注入HystrixCircuitBreakerConfiguration配置类
@Configuration public class HystrixCircuitBreakerConfiguration { @Bean public HystrixCommandAspect hystrixCommandAspect() { return new HystrixCommandAspect(); } @Bean public HystrixShutdownHook hystrixShutdownHook() { return new HystrixShutdownHook(); } @Bean public HasFeatures hystrixFeature() { return HasFeatures .namedFeatures(new NamedFeature("Hystrix", HystrixCommandAspect.class)); } /** * {@link DisposableBean} that makes sure that Hystrix internal state is cleared when * {@link ApplicationContext} shuts down. */ private class HystrixShutdownHook implements DisposableBean { @Override public void destroy() throws Exception { // Just call Hystrix to reset thread pool etc. Hystrix.reset(); } } }
在HystrixCircuitBreakerConfiguration配置类中注入了HystrixCommandAspect切面,
@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 { if (!metaHolder.isObservable()) { 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; } }
在项目中添加了HystrixCommand注解和HystrixCollapser注解的方法都会成为HystrixCommandAspect切面的切入点,methodsAnnotatedWithHystrixCommand方法实现了横切逻辑,这就是为什么给方法添加HystrixCommand注解可以实现熔断降级策略。
@HystrixCommand(
threadPoolKey = "testHystrix",
threadPoolProperties = {
@HystrixProperty(name="coreSize",value ="1"), // 线程数
@HystrixProperty(name="maxQueueSize",value="20") // 等待队列⻓度
},
commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="2000")
}
)
@GetMapping("/testHystrix/{userId}")
public Integer testHystrix(@PathVariable Long userId) {
......
}
版本信息
JDK:1.8
Spring Boot:2.1.9.RELEASE
Spring Cloud:Greenwich.SR3
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。