【SpringCloud源码】Hystrix的fallBack过程

6 篇文章 1 订阅
2 篇文章 0 订阅

Hystrix是SpringCloud全家桶中的熔断和隔离器,可实现服务的降级策咯、隔离策略、批量请求等等功能。

一般使用方法

1.pom.xml中添加:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2.Application添加注解@EnableCircuitBreaker

@SpringBootApplication
@EnableCircuitBreaker
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3.controller增加注解@HystrixCommand

@RestController
public class MyController {
    @HystrixCommand(fallbackMethod = "error")
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String start(){
        throw new RuntimeException();
//        return "start";
    }

    public String error(){
        return "error";
    }
}
@HystrixCommand注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {
    // 命令组key,用于将报告、报警、仪表盘等命令分组
    String groupKey() default "";
    // Hystrix命令key,默认为被修饰方法名
    String commandKey() default "";
    // HystrixThreadPool线程池的key,该key便于标识监控、度量发布、缓存中的线程池
    String threadPoolKey() default "";
    // 自定义的fallback方法
    String fallbackMethod() default "";
    // commandProperties相关参数
    HystrixProperty[] commandProperties() default {};
    // threadPoolProperties相关参数
    HystrixProperty[] threadPoolProperties() default {};
    // 可忽略的异常
    Class<? extends Throwable>[] ignoreExceptions() default {};
    // 分为LAZY和EAGER两种模式
    ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;
    // 添加Hystrix执行期间所包含的想要抛出的异常
    HystrixException[] raiseHystrixExceptions() default {};
    // 默认fallback方法
    String defaultFallback() default "";
}
@HystrixCommand注解执行过程

该注解也是基于aop实现的,其修饰的方法会进入HystrixCommandAspect中的methodsAnnotatedWithHystrixCommand()方法,该Aspect中仅实现了切面的Around方式。源码如下:

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

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

@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
    // 获取切点方法
    Method method = getMethodFromTarget(joinPoint);
    // 被修饰方法不能为null
    Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
    // @HystrixCommand和@HystrixCollapser不能同时使用
    if (method.isAnnotationPresent(.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
        throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
                "annotations at the same time");
    }
    // 构造metaHolderFactory根据类型(COMMAND和COLLAPSER)
    MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
    // 创建metaHolder,其中包含了各种必要信息,如注解的方法包含的各种信息以及fallback方法的各种信息,下面有源码
    MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
    // 创建一个可执行器,下面有源码
    HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
    // 设置类型SYNCHRONOUS、ASYNCHRONOUS、OBSERVABLE
    ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
            metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

    Object result;
    try {
        if (!metaHolder.isObservable()) {
            // 默认会执行这里,根据不同情况返回结果,也是通过Futrue方式执行请求,通过get()方法获取结果,下面有源码
            result = CommandExecutor.execute(invokable, executionType, metaHolder);
        } else {
            result = executeObservable(invokable, executionType, metaHolder);
        }
    } catch (HystrixBadRequestException e) {
        throw e.getCause() != null ? e.getCause() : e;
    } catch (HystrixRuntimeException e) {
        throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
    }
    return result;
}

metaHolderFactory.create(joinPoint)调用的create是MetaHolderFactory的重构方法,实际上是调用下面的create方法。

public abstract MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint);

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);
    // 此处就是添加fallback方法
    setFallbackMethod(builder, obj.getClass(), method);
    builder = setDefaultProperties(builder, obj.getClass(), joinPoint);
    return builder;
}

HystrixCommandFactory.getInstance().create(metaHolder)调用的create方法

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

最终的方法执行

public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
    Validate.notNull(invokable);
    Validate.notNull(metaHolder);

    switch (executionType) {
        case SYNCHRONOUS: {
            // 最终会执行这里的execute()方法,实际上调用的是queue().get()
            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);
    }
}
getFallback方法

上面一直没提到getFallback()方法,这个方法是在全流程中出现异常时,自动跳入的,源码中也有相关说明

/**
* The fallback is performed whenever a command execution fails.
*/
@Override
protected Object getFallback() {
    // 获取fallback方法的执行器
    final CommandAction commandAction = getFallbackAction();
    // 如果获取到了则执行
    if (commandAction != null) {
        try {
            return process(new Action() {
                @Override
                Object execute() {
                    MetaHolder metaHolder = commandAction.getMetaHolder();
                    Object[] args = createArgsForFallback(metaHolder, getExecutionException());
                    return commandAction.executeWithArgs(metaHolder.getFallbackExecutionType(), args);
                }
            });
        } catch (Throwable e) {
            LOGGER.error(FallbackErrorMessageBuilder.create()
                    .append(commandAction, e).build());
            throw new FallbackInvocationException(unwrapCause(e));
        }
    } else {
        return super.getFallback();
    }
}
HystrixCommandExecutionHook

可能看了源码很多人也都有疑问,为什么出现异常就会转入getFallback方法,这是由于Hystrix使用了hook钩子,中包含了很多未实现的抽象方法。仔细看源码会发现在最开始初始化各个Hystrix参数的时候就初始化了hook。

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());
    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);
    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;
}

最终的实现都是在ExecutionHookDeprecationWrapper类中实现的具体逻辑,该类是HystrixCommandExecutionHook抽象类的子类。

这就是Hystrix中getFallback方法的实现原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只努力的微服务

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值