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。
@Configurationpublic 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=truehystrix.command.default.circuitBreaker.requestVolumeThreshold=20hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000hystrix.command.default.circuitBreaker.errorThresholdPercentage=50hystrix.command.default.execution.isolation.strategy=THREADhystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000hystrix.command.default.execution.timeout.enabled=truehystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000hystrix.command.default.metrics.rollingStats.numBuckets=10hystrix.threadpool.default.coreSize=10hystrix.threadpool.default.maximumSize=10hystrix.threadpool.default.keepAliveTimeMinutes=1