【Hystrix】【源码+图解】【一】功能介绍及HelloWorld体验
3. 获取创建MetaHolder的工厂
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
......
// 1.1 拦截类型
// 1.2 根据类型获取工厂
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
......
}
3.1 拦截类型
private enum HystrixPointcutType {
COMMAND,
COLLAPSER;
// 拦截类型根据方法的注解来获取:
// @HystrixCommand -> COMMAND 单个
// @HystrixCollapser -> COLLAPSER 批量
static HystrixPointcutType of(Method method) {
if (method.isAnnotationPresent(HystrixCommand.class)) {
return COMMAND;
} else if (method.isAnnotationPresent(HystrixCollapser.class)) {
return COLLAPSER;
} else {
String methodInfo = getMethodInfo(method);
throw new IllegalStateException("'https://github.com/Netflix/Hystrix/issues/1458' - no valid annotation found for: \n" + methodInfo);
}
}
}
3.2 获取创建MetaHolder的工厂
// @HystrixCommand -> COMMAND -> CommandMetaHolderFactory
// @HystrixCollapser -> COLLAPSER -> CollapserMetaHolderFactory
static {
META_HOLDER_FACTORY_MAP = ImmutableMap.<HystrixPointcutType, MetaHolderFactory>builder()
.put(HystrixPointcutType.COMMAND, new CommandMetaHolderFactory())
.put(HystrixPointcutType.COLLAPSER, new CollapserMetaHolderFactory())
.build();
}
4. 创建MetaHolder
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);
......
// 从【3】中我们获得了工厂,以CommandMetaHolderFactory为例我们继续探讨create过程
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
......
}
CommandMetaHolderFactory.create()
public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
HystrixCommand hystrixCommand = method.getAnnotation(HystrixCommand.class);
// 【4.1】设置命令的执行类型
ExecutionType executionType = ExecutionType.getExecutionType(method.getReturnType());
// 【4.2】设置基础信息
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.1 设置命令的执行类型ExecutionType
public enum ExecutionType {
ASYNCHRONOUS,
SYNCHRONOUS,
OBSERVABLE;
// 根据方法返回值设置执行类型
public static ExecutionType getExecutionType(Class<?> type) {
if (Future.class.isAssignableFrom(type)) {
return ExecutionType.ASYNCHRONOUS;
} else if (Observable.class.isAssignableFrom(type)) {
return ExecutionType.OBSERVABLE;
} else {
return ExecutionType.SYNCHRONOUS;
}
}
}
4.2 设置MetaHolder信息
MetaHolderFactory.metaHolderBuilder()
MetaHolder.Builder metaHolderBuilder(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
MetaHolder.Builder builder = MetaHolder.builder()
.args(args).method(method).obj(obj).proxyObj(proxy)
.joinPoint(joinPoint);
// 【4.2.1】设置降级方法
setFallbackMethod(builder, obj.getClass(), method);
// 【4.2.2】设置默认属性
builder = setDefaultProperties(builder, obj.getClass(), joinPoint);
return builder;
}
4.2.1设置断路降级方法fallback
HystrixCommandAspect.setFallbackMethod()
private static MetaHolder.Builder setFallbackMethod(MetaHolder.Builder builder, Class<?> declaringClass, Method commandMethod) {
// 根据fallbackMethod的值在本类中查找fallback函数
FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(declaringClass, commandMethod);
// 判断是否存在
if (fallbackMethod.isPresent()) {
// 存在
// 校验,fallback函数的参数个数和类型、返回值的类型需要与原方法一致
fallbackMethod.validateReturnType(commandMethod);
builder
// 设置fallback方法
.fallbackMethod(fallbackMethod.getMethod())
// 设置执行类型
.fallbackExecutionType(ExecutionType.getExecutionType(fallbackMethod.getMethod().getReturnType()));
}
return builder;
}
4.2.2 设置默认属性
HystrixCommandAspect.setDefaultProperties()
private static MetaHolder.Builder setDefaultProperties(MetaHolder.Builder builder, Class<?> declaringClass, final ProceedingJoinPoint joinPoint) {
// 从方法所属的类或者父类获取@DefaultProperties
Optional<DefaultProperties> defaultPropertiesOpt = AopUtils.getAnnotation(joinPoint, DefaultProperties.class);
// 默认的GroupKey为类名
builder.defaultGroupKey(declaringClass.getSimpleName());
// 判断@DefaultProperties是否存在
if (defaultPropertiesOpt.isPresent()) {
DefaultProperties defaultProperties = defaultPropertiesOpt.get();
// 设置默认值
builder.defaultProperties(defaultProperties);
// 设置默认groupKey
if (StringUtils.isNotBlank(defaultProperties.groupKey())) {
builder.defaultGroupKey(defaultProperties.groupKey());
}
// 设置默认threadPoolKey
if (StringUtils.isNotBlank(defaultProperties.threadPoolKey())) {
builder.defaultThreadPoolKey(defaultProperties.threadPoolKey());
}
}
return builder;
}
@DefaultProperties
@Target({ElementType.TYPE}) // 只能放在类上,不能放在方法上
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DefaultProperties {
String groupKey() default ""; // 组名
String threadPoolKey() default ""; // 线程池名
HystrixProperty[] commandProperties() default {}; // 除了@HystrixCommand指定的其他命令属性
HystrixProperty[] threadPoolProperties() default {}; // 除了@HystrixCommand指定的其他线程池属性
Class<? extends Throwable>[] ignoreExceptions() default {}; // 声明忽略的异常
HystrixException[] raiseHystrixExceptions() default {};
String defaultFallback() default "";
}
5. 创建Hystrix命令
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);
......
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
// 创建Hystrix命令
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
......
}
5.1 Hystrix命令类型
Hystrix命令分三种:
- HystrixCommand
- HystrixObservableCommand
- HystrixCollapser
接下来我们通过类图看下它们之间的关系
通过类图我们可以看到主要分为四层来理解
(1)执行类型
Hystrix命令的执行类型有四种:同步阻塞、异步执行、hot观察者模式、cold冷观察者模式,而HystrixExecutable
定义了前两者,HystrixObservable
定义了后两者,而HystrixExecutable
与HystrixObservable
为接口,真正的实现则是由其实现类实现的,为了具体看下它们的不同,我们以HystrixCommand
和AbstractCommand
看下这四种模式的实现
HystrixCommand
// 返回具体结果
public R execute() {
try {
// 调用queue()方法获取Future对象,调用Future对象的调用get()方法进行阻塞直到获取结果,实现同步执行命令
return queue().get();
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}
// 返回一个Future对象,实现异步执行命令
public Future<R> queue() {
// 调用toObservable()获得观察对象,toBlocking()转为阻塞的观察者,toFuture()开启订阅并返回一个Futrue对象
final Future<R> delegate = toObservable().toBlocking().toFuture();
// 创建Future对象,包装delegate对象,处理delegate中可能出现的中断异常
final Future<R> f = new Future<R>() {
......
};
return f;
}
AbstractCommand
// 热观察者模式:只要调用了observe(),当事件到来的时候就能获得通知
public Observable<R> observe() {
// 缓存被订阅的被观察者
ReplaySubject<R> subject = ReplaySubject.create();
// 调用toObservable()获得观察对象,调用subscribe()开启订阅,实现热观察者模式
final Subscription sourceSubscription = toObservable().subscribe(subject);
return subject.doOnUnsubscribe(...);
}
// 冷观察者模式:调用toObservable()只是获得观察对象,如果不进行subscribe订阅,即使有消息也不会获得通知
public Observable<R> toObservable() {
......
return Observable.defer(...);
}
从源码可以看到,不管是同步阻塞的execute(),异步的queue(),热观察者模式的observe(),最终的底层都是调用了冷观察者模式的toObservable(),而toObservable()用到了RxJava响应式编程,也就是Hystrix其实是用RxJava构建的。从这一点来看,虽然Hystrix已经被废弃,研究Hystrix同时还能学习RxJava,也算是一箭双雕吧。
(2) Hystrix的缓存、断路器、隔离、信息统计等功能的具体实现
从(1)中我们看到最终都会到toObservable()方法,而toObservable()方法的实现在AbstractCommand
,这里涉及的内容过多,后面会讨论
(3) 切面中创建的Hystrix命令类型
HystrixCommandFactory.create()
public HystrixInvokable create(MetaHolder metaHolder) {
HystrixInvokable executable;
// 1. 如果方法注解是@HystrixCollapser,则创建CommandCollapser
// 2. 如果方法注解是@HystrixCommand且返回值类型为Observable,则创建GenericObservableCommand
// 3. 其他GenericCommand
if (metaHolder.isCollapserAnnotationPresent()) {
executable = new CommandCollapser(metaHolder);
} else if (metaHolder.isObservable()) {
executable = new GenericObservableCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
} else {
// 【3.2】
executable = new GenericCommand(HystrixCommandBuilderFactory.getInstance().create(metaHolder));
}
return executable;
}
从这可以看出Hystrix命令的具体实现有三种: CommandCollapser、GenericObservableCommand、GenericCommand,而后两者需要获得HystrixCommandBuilder
【5.2】
(4) 原方法逻辑的执行
后文分析
5.2 HystrixCommandBuilder
HystrixCommandBuilder
的功能主要是存储@HystrixCommand
配置的属性,为此先看看@HystrixCommand
都提供哪些属性的配置
public @interface HystrixCommand {
// 默认为类名
String groupKey() default "";
// 默认方法名
String commandKey() default "";
// 默认为groupKey()
String threadPoolKey() default "";
// 降级方法
String fallbackMethod() default "";
// 可配置的参数HystrixCommandProperties
HystrixProperty[] commandProperties() default {};
// 可配置的参数HystrixThreadPoolProperties
HystrixProperty[] threadPoolProperties() default {};
// 当抛出ignoreExceptions定义的异常时,不进行降级处理,直接往上抛异常
Class<? extends Throwable>[] ignoreExceptions() default {};
// EAGER -> observe()
// LAZY -> toObservable()
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;
// 将raiseHystrixExceptions包装成HystrixRuntimeException
HystrixException[] raiseHystrixExceptions() default {};
String defaultFallback() default "";
}
接下来我们看下HystrixCommandBuilder
如何存储这些参数
HystrixCommandBuilderFactory.getInstance().create(metaHolder)
public HystrixCommandBuilder create(MetaHolder metaHolder) {
return create(metaHolder, Collections.<HystrixCollapser.CollapsedRequest<Object, Object>>emptyList());
}
public <ResponseType> HystrixCommandBuilder create(MetaHolder metaHolder, Collection<HystrixCollapser.CollapsedRequest<ResponseType, Object>> collapsedRequests) {
validateMetaHolder(metaHolder);
return HystrixCommandBuilder.builder()
.setterBuilder(createGenericSetterBuilder(metaHolder)) // 【5.2.1】
.commandActions(createCommandActions(metaHolder)) // 【5.2.2】
.collapsedRequests(collapsedRequests) // 【5.2.3】
.cacheResultInvocationContext(createCacheResultInvocationContext(metaHolder)) // 【5.2.4】
.cacheRemoveInvocationContext(createCacheRemoveInvocationContext(metaHolder)) // 【5.2.5】
.ignoreExceptions(metaHolder.getCommandIgnoreExceptions()) // 【5.2.6】
.executionType(metaHolder.getExecutionType()) // 【5.2.7】
.build();
}
5.2.1 SetterBuilder
private GenericSetterBuilder createGenericSetterBuilder(MetaHolder metaHolder) {
GenericSetterBuilder.Builder setterBuilder = GenericSetterBuilder.builder()
.groupKey(metaHolder.getCommandGroupKey())
.threadPoolKey(metaHolder.getThreadPoolKey())
.commandKey(metaHolder.getCommandKey())
.collapserKey(metaHolder.getCollapserKey())
.commandProperties(metaHolder.getCommandProperties())
.threadPoolProperties(metaHolder.getThreadPoolProperties())
.collapserProperties(metaHolder.getCollapserProperties());
if (metaHolder.isCollapserAnnotationPresent()) {
setterBuilder.scope(metaHolder.getHystrixCollapser().scope());
}
return setterBuilder.build();
}
groupKey
public String getCommandGroupKey() {
// 如果有注解@HystrixCommand,则获取其groupKey的值,如果groupKey的值为空,则设置为默认值defaultGroupKey(类名)
// 如果没有注解@HystrixCommand,则设置为空值
return isCommandAnnotationPresent() ? get(hystrixCommand.groupKey(), defaultGroupKey) : "";
}
举个栗子,获取顺序myGroupKey > myDefaultGroupKey > 类名(UserFacadeImpl)
@DefaultProperties(groupKey = "myDefaultGroupKey")
public class UserFacadeImpl implements UserFacade{
@Override
@HystrixCommand(groupKey = "myGroupKey")
public ResultMessage getUser() {
return null;
}
}
threadPoolKey
获取顺序myThreadPoolKey > myDefaultThreadPoolKey > groupKey
public String getThreadPoolKey() {
return isCommandAnnotationPresent() ? get(hystrixCommand.threadPoolKey(), defaultThreadPoolKey) : "";
}
commandKey
默认方法名
collapserKey
public String getCollapserKey() {
return isCollapserAnnotationPresent() ? get(hystrixCollapser.collapserKey(), defaultCollapserKey) : "";
}
commandProperties
1 > 2 > 空值
@DefaultProperties(commandProperties = {} ) // 2
public class UserFacadeImpl implements UserFacade{
@HystrixCommand(commandProperties = {}) // 1
public void name() {
}
}
学以致用
举个栗子
@HystrixCommand(commandProperties = {
// THREAD,SEMAPHORE
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
// 最大并发量
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "30")}
)
public void test() {
}
更多可使用@HystrixProperty设置的参数可以参考HystrixCommandProperties
第115-138行
threadPoolProperties
与commandProperties类似,可参考HystrixThreadPoolProperties
collapserProperties
@HystrixCollapser(collapserProperties = {}, batchMethod = "")
public void name() {
}
可参考HystrixCollapserProperties
5.2.2 CommandActions
CommandAction
是原方法的执行方式,它的实现类MethodExecutionAction
使用反射的方式调用原方法并获取结果
private CommandActions createCommandActions(MetaHolder metaHolder) {
CommandAction commandAction = createCommandAction(metaHolder);
CommandAction fallbackAction = createFallbackAction(metaHolder);
return CommandActions.builder().commandAction(commandAction)
.fallbackAction(fallbackAction).build();
}
private CommandAction createCommandAction(MetaHolder metaHolder) {
// 将method进行包装
return new MethodExecutionAction(metaHolder.getObj(), metaHolder.getMethod(), metaHolder.getArgs(), metaHolder);
}
private CommandAction createFallbackAction(MetaHolder metaHolder) {
FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(metaHolder.getObj().getClass(),
metaHolder.getMethod(), metaHolder.isExtendedFallback());
fallbackMethod.validateReturnType(metaHolder.getMethod());
CommandAction fallbackAction = null;
// 如果有fallbackMethod
if (fallbackMethod.isPresent()) {
......
if (fallbackMethod.isCommand()) {
// @HystrixCommand注解
......
fallbackAction = new LazyCommandExecutionAction(fmMetaHolder);
} else {
......
fallbackAction = new MethodExecutionAction(fmMetaHolder.getObj(), fMethod, fmMetaHolder.getArgs(), fmMetaHolder);
}
}
return fallbackAction;
}
5.2.3 CollapsedRequests
默认空值
5.2.4 CacheResultInvocationContext
public static CacheInvocationContext<CacheResult> createCacheResultInvocationContext(MetaHolder metaHolder) {
Method method = metaHolder.getMethod();
// 如果注解了@CacheResult,创建缓存上下文
if (method.isAnnotationPresent(CacheResult.class)) {
CacheResult cacheResult = method.getAnnotation(CacheResult.class);
// 创建生成缓存key的方法
MethodExecutionAction cacheKeyMethod = createCacheKeyAction(cacheResult.cacheKeyMethod(), metaHolder);
return new CacheInvocationContext<CacheResult>(cacheResult, cacheKeyMethod, metaHolder.getObj(), method, metaHolder.getArgs());
}
return null;
}
private static MethodExecutionAction createCacheKeyAction(String method, MetaHolder metaHolder) {
MethodExecutionAction cacheKeyAction = null;
// 如果@CacheResult中声明了cacheKeyMethod则创建其执行操作,否则返回null
if (StringUtils.isNotBlank(method)) {
Method cacheKeyMethod = getDeclaredMethod(metaHolder.getObj().getClass(), method,
metaHolder.getMethod().getParameterTypes());
// cacheKeyMethod方法在同一个类中有定义,否则抛异常
if (cacheKeyMethod == null) {
......
}
// cacheKeyMethod返回类型必须为String类型,否则抛异常
if (!cacheKeyMethod.getReturnType().equals(String.class)) {
......
}
MetaHolder cMetaHolder = MetaHolder.builder().obj(metaHolder.getObj()).method(cacheKeyMethod).args(metaHolder.getArgs()).build();
cacheKeyAction = new MethodExecutionAction(cMetaHolder.getObj(), cacheKeyMethod, cMetaHolder.getArgs(), cMetaHolder);
}
return cacheKeyAction;
}
5.2.5 cacheRemoveInvocationContext
@CacheRemove的定义,与CacheResultInvocationContext类似
5.2.6 ignoreExceptions
与commandProperties类似
5.2.7 ExecutionType
2.1设置的值