SpringCloud Hystrix 部分源码

1:在 spring-cloud-netflix-core 的 spring.factories 里面有对EnableCircuitBreaker的配置

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration 

2:在 HystrixCircuitBreakerConfiguration 里,会实例化 HystrixCommandAspect。在该切面里面,会处理@HystrixCommand 和 @HystrixCollapser。

@Configuration
public class HystrixCircuitBreakerConfiguration {

    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    } 

SpringCloud Hystrix 部分源码_第1张图片

image.png

3:注解@HystrixCommand 的解析代码如下:

private static class CommandMetaHolderFactory extends MetaHolderFactory {
        @Override
        public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
            HystrixCommand hystrixCommand = method.getAnnotation(HystrixCommand.class);
            ExecutionType executionType = ExecutionType.getExecutionType(method.getReturnType());
            MetaHolder.Builder builder = metaHolderBuilder(proxy, method, obj, args, joinPoint);
            if (isCompileWeaving()) {
                builder.ajcMethod(getAjcMethodFromTarget(joinPoint));
            }
            return builder.defaultCommandKey(method.getName())
                            .hystrixCommand(hystrixCommand)
                            .observableExecutionMode(hystrixCommand.observableExecutionMode())
                            .executionType(executionType)
                            .observable(ExecutionType.OBSERVABLE == executionType)
                            .build();
        }
    } 

4:对于@HystrixCommand 注解,创建的实例是:GenericCommand,如下:

public HystrixInvokable create(MetaHolder metaHolder) {
        HystrixInvokable executable;
        if (metaHolder.isCollapserAnnotationPresent()) {
            executable = new CommandCollapser(metaHolder);
        } else if (metaHolder.isObservable()) {
            executable = new GenericObservableCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
        } else {
            executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
        }
        return executable;
    } 

5:GenericCommand 的构造函数中,会初始化参数,比如commandKey。

protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool,
            HystrixCommandProperties.Setter commandPropertiesDefaults, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults,
            HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore executionSemaphore,
            HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook) {

        this.commandGroup = initGroupKey(group); //默认值是类名
        this.commandKey = initCommandKey(key, getClass()); //默认值是方法名
        // 加载属性,HystrixCommandProperties
        this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
        this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get()); //默认值是类名
        this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.properties);  //构造HystrixCommandMetrics
        //创建断路器实例:HystrixCircuitBreakerImpl
        this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics); 
        // 初始化线程池
        this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);

        //Strategies from plugins
        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(this.properties.requestLogEnabled().get(), this.concurrencyStrategy);

        /* fallback semaphore override if applicable */
        this.fallbackSemaphoreOverride = fallbackSemaphore;

        /* execution semaphore override if applicable */
        this.executionSemaphoreOverride = executionSemaphore;
    } 

6:创建完成GenericCommand对象后,执行下面的代码执行切面函数。实际执行的是这个函数:com.netflix.hystrix.HystrixCommand#execute

Object result;
        try {
            if (!metaHolder.isObservable()) {
                result = CommandExecutor.execute(invokable, executionType, metaHolder);
            } else {
                result = executeObservable(invokable, executionType, metaHolder);
            } 

7:由于Hystrix的监控源码是才有rxjava编写,所以在这里没有展开。
8:Hystrix的配置属性和默认值(比如隔离级别,超时时间,请求数量,错误率等)在这2个类:HystrixCommandProperties 和 HystrixThreadPoolProperties。

9:@HystrixCommand 使用事例:

@HystrixCommand(fallbackMethod = "fastFailed", groupKey = "testKey",
            commandKey = "addUserKey", threadPoolKey = "testPoolKey",
            commandProperties = {@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "65000"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "50"),
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "20")},
            threadPoolProperties = {@HystrixProperty(name = "coreSize", value = "50"),
                    @HystrixProperty(name = "maximumSize", value = "100"),
                    @HystrixProperty(name = "maxQueueSize", value = "1000")})
    @RequestMapping(value = "/call", method = RequestMethod.GET)
    public String addUserClient(HttpServletRequest request) {
        String url = "http://appService/user/add";
        Map param = new HashMap<>();
        param.put("userName", "testUser");
        param.put("desc", "hystrix test.");
        String ret = restTemplate.postForObject(url, param, String.class);
        System.out.println(ret);
        return "OK";
    } 

10:application.properties 的配置例子:

hystrix.command.default.circuitBreaker.enabled=true
hystrix.command.default.circuitBreaker.requestVolumeThreshold=20
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
hystrix.command.default.execution.isolation.strategy=THREAD
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
hystrix.command.default.execution.timeout.enabled=true
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000
hystrix.command.default.metrics.rollingStats.numBuckets=10
hystrix.threadpool.default.coreSize=10
hystrix.threadpool.default.maximumSize=10
hystrix.threadpool.default.keepAliveTimeMinutes=1

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