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 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