Hystrix源码分析

Hystrix的源码需要有一定基础rxjava,所以接下来的源码分析会很简单,因为作者只是想了解下Hystrix整个流程,对rxjava不熟悉。

Hystrix源码

Feign已经整合了Hystrix,那里面是如何工作的呢?配置文件中feign.hystrix.enabled=true,那我们为什么需要这个配置呢?

首先我们看下FeignClientsConfiguration,这个文件加载的时候,里面的bean也会相应的加载到容器中,其中有一个Bean时Builder

@Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({HystrixCommand.class, HystrixFeign.class})
    protected static class HystrixFeignConfiguration {
        protected HystrixFeignConfiguration() {
        }

        @Bean
        @Scope("prototype")
        @ConditionalOnMissingBean
        @ConditionalOnProperty(
            name = {"feign.hystrix.enabled"}
        )
        public Builder feignHystrixBuilder() {
            return HystrixFeign.builder();
        }
    }

开启了Hystrix,Builder的Bean类则会是HystrixFeign而就不是Feign了。有了HystrixFeign这个类,我们可以查到FeignAutoConfiguration类中

@Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass(
        name = {"feign.hystrix.HystrixFeign"}
    )
    protected static class HystrixFeignTargeterConfiguration {
        protected HystrixFeignTargeterConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean
        public Targeter feignTargeter() {
            return new HystrixTargeter();
        }
    }

生成HystrixTargeter类,调用FeignClientFactoryBean类中getObject的方法时,Builder和Target对象就是之前说的两个。

public  T target(FeignClientFactoryBean factory, Builder feign, FeignContext context, HardCodedTarget target) {
        if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
            return feign.target(target);
        } else {
            feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder)feign;
            String name = StringUtils.isEmpty(factory.getContextId()) ? factory.getName() : factory.getContextId();
            SetterFactory setterFactory = (SetterFactory)this.getOptional(name, context, SetterFactory.class);
            if (setterFactory != null) {
                builder.setterFactory(setterFactory);
            }

            Class fallback = factory.getFallback();
            if (fallback != Void.TYPE) {
                return this.targetWithFallback(name, context, target, builder, fallback);
            } else {
                Class fallbackFactory = factory.getFallbackFactory();
                return fallbackFactory != Void.TYPE ? this.targetWithFallbackFactory(name, context, target, builder, fallbackFactory) : feign.target(target);
            }
        }
    }

HystrixTargeter.target核心方法,先加载fallback,没有则加载fallbackFactory,这个可以说明fallback的优先级高。接下来查看targetwithFallback方法

Feign build(final FallbackFactory nullableFallbackFactory) {
            super.invocationHandlerFactory(new InvocationHandlerFactory() {
                public InvocationHandler create(Target target, Map dispatch) {
                    return new HystrixInvocationHandler(target, dispatch, Builder.this.setterFactory, nullableFallbackFactory);
                }
            });
            super.contract(new HystrixDelegatingContract(this.contract));
            return super.build();
        }

生成HystrixInvocationHandler实例,并且执行父类的build().

public Feign build() {
            Factory synchronousMethodHandlerFactory = new Factory(this.client, this.retryer, this.requestInterceptors, this.logger, this.logLevel, this.decode404, this.closeAfterDecode, this.propagationPolicy);
            ParseHandlersByName handlersByName = new ParseHandlersByName(this.contract, this.options, this.encoder, this.decoder, this.queryMapEncoder, this.errorDecoder, synchronousMethodHandlerFactory);
            return new ReflectiveFeign(handlersByName, this.invocationHandlerFactory, this.queryMapEncoder);
        }

赋值,生成ReflectiveFeign执行其newInstance方法。接下来和Fiegn流程差不多,但是需要注意的是,调用提供者的时候HystrixInvocationHandler会先拦截其动作,调用其invoke方法

public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
        if (!"equals".equals(method.getName())) {
            if ("hashCode".equals(method.getName())) {
                return this.hashCode();
            } else if ("toString".equals(method.getName())) {
                return this.toString();
            } else {
                HystrixCommand hystrixCommand = new HystrixCommand((Setter)this.setterMethodMap.get(method)) {
                    protected Object run() throws Exception {
                        try {
                            return ((MethodHandler)HystrixInvocationHandler.this.dispatch.get(method)).invoke(args);
                        } catch (Exception var2) {
                            throw var2;
                        } catch (Throwable var3) {
                            throw (Error)var3;
                        }
                    }

                    protected Object getFallback() {
                        if (HystrixInvocationHandler.this.fallbackFactory == null) {
                            return super.getFallback();
                        } else {
                            try {
                                Object fallback = HystrixInvocationHandler.this.fallbackFactory.create(this.getExecutionException());
                                Object result = ((Method)HystrixInvocationHandler.this.fallbackMethodMap.get(method)).invoke(fallback, args);
                                if (HystrixInvocationHandler.this.isReturnsHystrixCommand(method)) {
                                    return ((HystrixCommand)result).execute();
                                } else if (HystrixInvocationHandler.this.isReturnsObservable(method)) {
                                    return ((Observable)result).toBlocking().first();
                                } else if (HystrixInvocationHandler.this.isReturnsSingle(method)) {
                                    return ((Single)result).toObservable().toBlocking().first();
                                } else if (HystrixInvocationHandler.this.isReturnsCompletable(method)) {
                                    ((Completable)result).await();
                                    return null;
                                } else {
                                    return HystrixInvocationHandler.this.isReturnsCompletableFuture(method) ? ((Future)result).get() : result;
                                }
                            } catch (IllegalAccessException var3) {
                                throw new AssertionError(var3);
                            } catch (ExecutionException | InvocationTargetException var4) {
                                throw new AssertionError(var4.getCause());
                            } catch (InterruptedException var5) {
                                Thread.currentThread().interrupt();
                                throw new AssertionError(var5.getCause());
                            }
                        }
                    }
                };
                if (Util.isDefault(method)) {
                    return hystrixCommand.execute();
                } else if (this.isReturnsHystrixCommand(method)) {
                    return hystrixCommand;
                } else if (this.isReturnsObservable(method)) {
                    return hystrixCommand.toObservable();
                } else if (this.isReturnsSingle(method)) {
                    return hystrixCommand.toObservable().toSingle();
                } else if (this.isReturnsCompletable(method)) {
                    return hystrixCommand.toObservable().toCompletable();
                } else {
                    return this.isReturnsCompletableFuture(method) ? new ObservableCompletableFuture(hystrixCommand) : hystrixCommand.execute();
                }
            }
        } else {
            try {
                Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                return this.equals(otherHandler);
            } catch (IllegalArgumentException var5) {
                return false;
            }
        }
    } 
  

这个类便为我们提供了Hystrix的实现。生成的实例HystrixCommand,该实例初始化线程池,熔断器和其他配置等

protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, Setter commandPropertiesDefaults, com.netflix.hystrix.HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults, HystrixCommandMetrics metrics, AbstractCommand.TryableSemaphore fallbackSemaphore, AbstractCommand.TryableSemaphore executionSemaphore, HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook) {
        this.commandState = new AtomicReference(AbstractCommand.CommandState.NOT_STARTED);
        this.threadState = new AtomicReference(AbstractCommand.ThreadState.NOT_USING_THREAD);
        this.executionResult = ExecutionResult.EMPTY;
        this.isResponseFromCache = false;
        this.commandStartTimestamp = -1L;
        this.isCommandTimedOut = new AtomicReference(AbstractCommand.TimedOutStatus.NOT_EXECUTED);
        this.commandGroup = initGroupKey(group);
        this.commandKey = initCommandKey(key, this.getClass());
        this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
        this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, (String)this.properties.executionIsolationThreadPoolKeyOverride().get());
        this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.properties);
        this.circuitBreaker = initCircuitBreaker((Boolean)this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
        this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);
        this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
        this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
        HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.properties);
        this.executionHook = initExecutionHook(executionHook);
        this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy);
        this.currentRequestLog = initRequestLog((Boolean)this.properties.requestLogEnabled().get(), this.concurrencyStrategy);
        this.fallbackSemaphoreOverride = fallbackSemaphore;
        this.executionSemaphoreOverride = executionSemaphore;
    }

每次调用的时候,只有再第一次调用的时候才会创建资源,以HystrixThreadPool为例

static HystrixThreadPool getInstance(HystrixThreadPoolKey threadPoolKey, Setter propertiesBuilder) {
            String key = threadPoolKey.name();
            HystrixThreadPool previouslyCached = (HystrixThreadPool)threadPools.get(key);
            if (previouslyCached != null) {
                return previouslyCached;
            } else {
                Class var4 = HystrixThreadPool.class;
                synchronized(HystrixThreadPool.class) {
                    if (!threadPools.containsKey(key)) {
                        threadPools.put(key, new HystrixThreadPool.HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
                    }
                }

                return (HystrixThreadPool)threadPools.get(key);
            }
        }
static final ConcurrentHashMap threadPools = new ConcurrentHashMap();

如果threadPools里面没有则新建,有的话则从pools中拿出来。

初始化之后,执行excute,

public R execute() {
        try {
            return this.queue().get();
        } catch (Exception var2) {
            throw Exceptions.sneakyThrow(this.decomposeException(var2));
        }
    }

该方法是同步,调用后直接阻塞,直到依赖服务返回单条结果,或抛异常。继续调用queue方法,queue的方法是异步,该command在线程池上排队,并在完成后返回一个 Future 以获取结果。无论是哪种执行command的方式,最终都是依赖toObservable().

关注一下applyHystrixSemantics方法

private Observable applyHystrixSemantics(AbstractCommand _cmd) {
        this.executionHook.onStart(_cmd);
        if (this.circuitBreaker.allowRequest()) {
            final AbstractCommand.TryableSemaphore executionSemaphore = this.getExecutionSemaphore();
            final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
            Action0 singleSemaphoreRelease = new Action0() {
                public void call() {
                    if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
                        executionSemaphore.release();
                    }

                }
            };
            Action1 markExceptionThrown = new Action1() {
                public void call(Throwable t) {
                    AbstractCommand.this.eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, AbstractCommand.this.commandKey);
                }
            };
            if (executionSemaphore.tryAcquire()) {
                try {
                    this.executionResult = this.executionResult.setInvocationStartTime(System.currentTimeMillis());
                    return this.executeCommandAndObserve(_cmd).doOnError(markExceptionThrown).doOnTerminate(singleSemaphoreRelease).doOnUnsubscribe(singleSemaphoreRelease);
                } catch (RuntimeException var7) {
                    return Observable.error(var7);
                }
            } else {
                return this.handleSemaphoreRejectionViaFallback();
            }
        } else {
            return this.handleShortCircuitViaFallback();
        }
    }

allowRequest是判断断路器是否开启关闭状态。如果开启,直接执行fallback降级;如果关闭进行健康检查,并继续执行。

public boolean allowRequest() {
            if ((Boolean)this.properties.circuitBreakerForceOpen().get()) {
                return false;
            } else if ((Boolean)this.properties.circuitBreakerForceClosed().get()) {
                this.isOpen();
                return true;
            } else {
                return !this.isOpen() || this.allowSingleTest();
            }
        }

        public boolean allowSingleTest() {
            long timeCircuitOpenedOrWasLastTested = this.circuitOpenedOrLastTestedTime.get();
            return this.circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + (long)(Integer)this.properties.circuitBreakerSleepWindowInMilliseconds().get() && this.circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis());
        }

        public boolean isOpen() {
            if (this.circuitOpen.get()) {
                return true;
            } else {
                HealthCounts health = this.metrics.getHealthCounts();
                if (health.getTotalRequests() < (long)(Integer)this.properties.circuitBreakerRequestVolumeThreshold().get()) {
                    return false;
                } else if (health.getErrorPercentage() < (Integer)this.properties.circuitBreakerErrorThresholdPercentage().get()) {
                    return false;
                } else if (this.circuitOpen.compareAndSet(false, true)) {
                    this.circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
                    return true;
                } else {
                    return true;
                }
            }
        }

我们需要关注,allowSingleTest,如果断路器开启了,我们允许一个进行测试,连接成功并且短路开启时间+休眠的时间或者上一次执行测试请求时间已经到了则断路器关闭,不行则打开。

接着尝试获取信号量实例,如果获取不到,则也失败(hystrix的隔离模式有信号量和线程池2种,这里如果没开启信号量模式,这里的TryableSemaphore tryAcquire默认返回的都是true),接着在进入executeCommandAndObserve方法。后续则失败进入fallback处理,或者进行run方法。

fallback处理会取出我们之前已经在配置的类,调用返回。

run方法如果正常处理的话,则会调用SynchronousMethodHandler进行后续处理,与Feign源码一致;

总结一下:Hystrix源码还是很难阅读,但是不影响我们跟踪代码,通过跟踪代码会很清楚的了解到代码运行。尽量debug模式去查看代码。Hystrix暂时到这,后续会补上新的理解。

 

 

你可能感兴趣的:(Hystrix源码分析)