乐趣区

关于java: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();
    } 

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<String, Object> 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
退出移动版