序
本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration
HystrixCircuitBreakerConfiguration
spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/hystrix/HystrixCircuitBreakerConfiguration.java
@Configurationpublic 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)); } //FIXME: 2.0.0 /*@Configuration @ConditionalOnProperty(value = "hystrix.metrics.enabled", matchIfMissing = true) @ConditionalOnClass({ HystrixMetricsPoller.class, GaugeService.class }) @EnableConfigurationProperties(HystrixMetricsProperties.class) protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle { private static Log logger = LogFactory .getLog(HystrixMetricsPollerConfiguration.class); @Autowired(required = false) private GaugeService gauges; @Autowired private HystrixMetricsProperties metricsProperties; private ObjectMapper mapper = new ObjectMapper(); private HystrixMetricsPoller poller; private Setreserved = new HashSet (Arrays.asList("group", "name", "type", "currentTime")); @Override public void start() { if (this.gauges == null) { return; } MetricsAsJsonPollerListener listener = new MetricsAsJsonPollerListener() { @Override public void handleJsonMetric(String json) { try { @SuppressWarnings("unchecked") Map map = HystrixMetricsPollerConfiguration.this.mapper .readValue(json, Map.class); if (map != null && map.containsKey("type")) { addMetrics(map, "hystrix."); } } catch (IOException ex) { // ignore } } }; this.poller = new HystrixMetricsPoller(listener, metricsProperties.getPollingIntervalMs()); // start polling and it will write directly to the listener this.poller.start(); logger.info("Starting poller"); } private void addMetrics(Map map, String root) { StringBuilder prefixBuilder = new StringBuilder(root); if (map.containsKey("type")) { prefixBuilder.append((String) map.get("type")); if (map.containsKey("group")) { prefixBuilder.append(".").append(map.get("group")); } prefixBuilder.append(".").append(map.get("name")); } String prefix = prefixBuilder.toString(); for (String key : map.keySet()) { Object value = map.get(key); if (!this.reserved.contains(key)) { if (value instanceof Number) { String name = prefix + "." + key; this.gauges.submit(name, ((Number) value).doubleValue()); } else if (value instanceof Map) { @SuppressWarnings("unchecked") Map sub = (Map ) value; addMetrics(sub, prefix); } } } } @Override public void stop() { if (this.poller != null) { this.poller.shutdown(); } } @Override public boolean isRunning() { return this.poller != null ? this.poller.isRunning() : false; } @Override public int getPhase() { return Ordered.LOWEST_PRECEDENCE; } @Override public boolean isAutoStartup() { return true; } @Override public void stop(Runnable callback) { if (this.poller != null) { this.poller.shutdown(); } callback.run(); } }*/ /** * {@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(); } }}复制代码
这里主要是创建了HystrixCommandAspect以及HystrixShutdownHook
HystrixCommandAspect
hystrix-javanica-1.5.12-sources.jar!/com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect.java
/** * AspectJ aspect to process methods which annotated with {@link HystrixCommand} annotation. */@Aspectpublic class HystrixCommandAspect { private static final MapMETA_HOLDER_FACTORY_MAP; static { META_HOLDER_FACTORY_MAP = ImmutableMap. 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() != null ? e.getCause() : e; } catch (HystrixRuntimeException e) { throw hystrixRuntimeExceptionToThrowable(metaHolder, e); } return result; } //......}复制代码
支持@HystrixCommand及@HystrixCollapser注解
HystrixShutdownHook
/** * {@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(); } }复制代码
主要是调用了reset方法
hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/Hystrix.java
/** * Reset state and release resources in use (such as thread-pools). ** NOTE: This can result in race conditions if HystrixCommands are concurrently being executed. *
*/ public static void reset() { // shutdown thread-pools HystrixThreadPool.Factory.shutdown(); _reset(); } /** * Reset state and release resources in use (such as threadpools) and wait for completion. ** NOTE: This can result in race conditions if HystrixCommands are concurrently being executed. *
* * @param time * time to wait for thread-pools to shutdown * @param unit * {@link TimeUnit} fortimeto wait for thread-pools to shutdown */ public static void reset(long time, TimeUnit unit) { // shutdown thread-pools HystrixThreadPool.Factory.shutdown(time, unit); _reset(); } /** * Reset logic that doesn't have time/TimeUnit arguments. */ private static void _reset() { // clear metrics HystrixCommandMetrics.reset(); HystrixThreadPoolMetrics.reset(); HystrixCollapserMetrics.reset(); // clear collapsers HystrixCollapser.reset(); // clear circuit breakers HystrixCircuitBreaker.Factory.reset(); HystrixPlugins.reset(); HystrixPropertiesFactory.reset(); currentCommand.set(new ConcurrentStack()); }复制代码
小结
HystrixCircuitBreakerConfiguration主要是注入了HystrixCommandAspect以及HystrixShutdownHook。前者用于支持支持@HystrixCommand及@HystrixCollapser注解,后者用于shudown的时候进行一些清理工作。