【Hystrix】【源码+图解】【二】创建Hystrix命令

【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命令分三种:

  1. HystrixCommand
  2. HystrixObservableCommand
  3. HystrixCollapser

接下来我们通过类图看下它们之间的关系

请添加图片描述

通过类图我们可以看到主要分为四层来理解

(1)执行类型

Hystrix命令的执行类型有四种:同步阻塞、异步执行、hot观察者模式、cold冷观察者模式,而HystrixExecutable定义了前两者,HystrixObservable定义了后两者,而HystrixExecutableHystrixObservable为接口,真正的实现则是由其实现类实现的,为了具体看下它们的不同,我们以HystrixCommandAbstractCommand看下这四种模式的实现

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设置的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值