博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud Hystrix源码分析(转)
阅读量:4040 次
发布时间:2019-05-24

本文共 8573 字,大约阅读时间需要 28 分钟。

转自:

如何使用Spring Cloud Hystrix进行服务容错保护

之前在这篇文章中,介绍过Spring Cloud Hystrix的使用,这里再回顾下:

1.启动类添加@EnableHystrix注解。
2.方法上添加@HystrixCommand注解,并指定fallback的方法。

Spring Cloud Hystrix源码分析

既然加了@EnableHystrix注解,那还是先进入这个注解看吧:

/** * Convenience annotation for clients to enable Hystrix circuit breakers (specifically). * Use this (optionally) in case you want discovery and know for sure that it is Hystrix * you want. All it does is turn on circuit breakers and let the autoconfiguration find * the Hystrix classes if they are available (i.e. you need Hystrix on the classpath as * well). * * @author Dave Syer * @author Spencer Gibb */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@EnableCircuitBreakerpublic @interface EnableHystrix {}

这个注解的功能就是开启Hystrix。这个注解还引入了@EnableCircuitBreaker注解。

在代码同一级目录下,还可以看到两个配置类:HystrixAutoConfiguration和HystrixCircuitBreakerConfiguration。

下面是HystrixAutoConfiguration配置类的配置:

@Configuration@ConditionalOnClass({ Hystrix.class, HealthIndicator.class })@AutoConfigureAfter({ HealthIndicatorAutoConfiguration.class })public class HystrixAutoConfiguration {    @Bean    @ConditionalOnEnabledHealthIndicator("hystrix")    public HystrixHealthIndicator hystrixHealthIndicator() {        return new HystrixHealthIndicator();    }}

从代码中可以看到,HystrixAutoConfiguration这个配置类主要是hystrix的健康检查的配置。再看下HystrixCircuitBreakerConfiguration这个类,这个类里面就配置了很多内容。

@Beanpublic HystrixCommandAspect hystrixCommandAspect() {    return new HystrixCommandAspect();}

这里返回了HystrixCommandAspect的bean,这个切面中定义了Pointcut:

@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")public void hystrixCommandAnnotationPointcut() {}@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")public void hystrixCollapserAnnotationPointcut() {}

所以,这个Aspect就是利用AOP切面对 HystrixCommand 、 HystrixCollapser 两种注解的方法进行扩展处理。

我们在方法上添加@HystrixCommand注解,就会经过这个切面,这个切面中定义了@Around(…)拦截所有请求。

下面看下这个方法:

@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {    Method method = getMethodFromTarget(joinPoint);    Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);    if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {        throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +                "annotations at the same time");    }    MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));    MetaHolder metaHolder = metaHolderFactory.create(joinPoint);    HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);    ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?            metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();    Object result;    try {        result = CommandExecutor.execute(invokable, executionType, metaHolder);    } catch (HystrixBadRequestException e) {        throw e.getCause();    }    return result;}

这个方法中,一开始先获取拦截的Method,然后判断,如果方法上同时加了@HystrixCommand和@HystrixCollapser两个注解的话,就抛异常。

在创建MetaHolder的时候,调用了MetaHolderFactory的create方法,MetaHolderFactory有两个子类,CollapserMetaHolderFactory和CommandMetaHolderFactory,最终执行的是子类的create方法,下面是CommandMetaHolderFactory中的create方法:

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);        return builder.defaultCommandKey(method.getName())                        .hystrixCommand(hystrixCommand)                        .observableExecutionMode(hystrixCommand.observableExecutionMode())                        .executionType(executionType)                        .observable(ExecutionType.OBSERVABLE == executionType)                        .build();    }}
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)            .defaultGroupKey(obj.getClass().getSimpleName())            .joinPoint(joinPoint);    if (isCompileWeaving()) {        builder.ajcMethod(getAjcMethodFromTarget(joinPoint));    }    FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(obj.getClass(), method);    if (fallbackMethod.isPresent()) {        fallbackMethod.validateReturnType(method);        builder                .fallbackMethod(fallbackMethod.getMethod())                .fallbackExecutionType(ExecutionType.getExecutionType(fallbackMethod.getMethod().getReturnType()));    }    return builder;}
  • 在创建MetaHolder的过程中,就会指定fallback方法。
    创建完MetaHolder之后,就会根据MetaHolder创建HystrixInvokable。
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;}

这段代码里定义了后续真正执行HystrixCommand的GenericCommand实例

方法最终会去执行CommandExecutor.execute方法:

public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {    Validate.notNull(invokable);    Validate.notNull(metaHolder);    switch (executionType) {        case SYNCHRONOUS: {            return castToExecutable(invokable, executionType).execute();        }        case ASYNCHRONOUS: {            HystrixExecutable executable = castToExecutable(invokable, executionType);            if (metaHolder.hasFallbackMethodCommand()                    && ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {                return new FutureDecorator(executable.queue());            }            return executable.queue();        }        case OBSERVABLE: {            HystrixObservable observable = castToObservable(invokable);            return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();        }        default:            throw new RuntimeException("unsupported execution type: " + executionType);    }}
  • 这里会分成同步和异步的场景,进入execute方法看下:
/** * Used for synchronous execution of command. *  * @return R *         Result of {@link #run()} execution or a fallback from {@link #getFallback()} if the command fails for any reason. * @throws HystrixRuntimeException *             if a failure occurs and a fallback cannot be retrieved * @throws HystrixBadRequestException *             if invalid arguments or state were used representing a user failure, not a system failure * @throws IllegalStateException *             if invoked more than once */public R execute() {    try {        return queue().get();    } catch (Exception e) {        throw decomposeException(e);    }}
  • 这个方法的注释中说明了返回值,可以返回请求的结果,当失败的时候,则会通过getFallback()方法来执行一个回退操作,由于是GenericCommand实例,那就看下这个实例中的getFallback()方法:
@Overrideprotected Object getFallback() {    if (getFallbackAction() != null) {        final CommandAction commandAction = getFallbackAction();        try {            return process(new Action() {                @Override                Object execute() {                    MetaHolder metaHolder = commandAction.getMetaHolder();                    Object[] args = createArgsForFallback(metaHolder, getExecutionException());                    return commandAction.executeWithArgs(commandAction.getMetaHolder().getFallbackExecutionType(), args);                }            });        } catch (Throwable e) {            LOGGER.error(FallbackErrorMessageBuilder.create()                    .append(commandAction, e).build());            throw new FallbackInvocationException(e.getCause());        }    } else {        return super.getFallback();    }}

看到这里,大体的一个流程也就知道了,就是通过HystrixCommandAspect,请求成功返回接口的结果,请求失败执行fallback的逻辑。感兴趣的同学可以再仔细梳理下代码。

转载地址:http://hxadi.baihongyu.com/

你可能感兴趣的文章
1051. Pop Sequence (25) 判断出栈序列是否合理
查看>>
判断出栈序列是否合理
查看>>
1026. Table Tennis (30)
查看>>
1028. List Sorting (25) COUT和 cin 超时
查看>>
1064. Complete Binary Search Tree (30)
查看>>
1098. Insertion or Heap Sort (25)
查看>>
1099. Build A Binary Search Tree (30) 给定二叉搜索树插值
查看>>
1083. List Grades (25)
查看>>
1036. Boys vs Girls (25)
查看>>
1094. The Largest Generation (25)
查看>>
1056. Mice and Rice (25)
查看>>
1030. Travel Plan (30)寻找最短路径
查看>>
1053. Path of Equal Weight (30)
查看>>
1073. Scientific Notation (20)
查看>>
1037. Magic Coupon (25)
查看>>
1040. Longest Symmetric String (25) 最长回文子串
查看>>
1090. Highest Price in Supply Chain (25)
查看>>
1063. Set Similarity (25) 并查集
查看>>
1062. Talent and Virtue (25) 排序
查看>>
1093. Count PAT's (25)
查看>>