Spring Cloud Hystrix 源码系列:工作原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/itsoftchenfei/article/details/85069742

Hystrix 译为 "豪猪",豪猪的棘刺能保护自己不受天敌伤害,代表了强大的防御能力。Hystrix 基于 RxJava 进行实现,RxJava 是一种基于观察者模式的响应式编程框架。Spring Cloud Hystrix 基于 Netflix Hystrix 实现,具备服务降级、服务熔断、线程与信号隔离、请求缓存、请求合并以及服务监控等强大功能。

目录

1. 由来

2. 功能介绍

3. 工作原理

3.1 构建命令

3.2 执行命令

3.3 检查缓存

3.4 断路器是否打开

3.5 检查线程池/信号量情况

3.6 执行任务

3.7 断路器健康检查

3.8 失败时执行 Fallback

3.9 返回执行结果

4. 源码解析

4.1 HystrixCommandAspect

4.2 HystrixCommandKey和HystrixCommandGroupKey和HystrixThreadPoolKey

4.3 AbstractCommand.toObservable


1. 由来

在单体应用中,一类服务、一个线程、一个Bug等局部因素压垮整个系统也是屡见不鲜。微服务中,服务间依赖重重,通过隔离,很好的控制住风险范围,再结合请求拒绝和超时控制,有效剔除 “老鼠屎”,避免坏了一锅粥。总之,隔离设计是绝妙的防护罩。Netflix 将该组件取名为 Hystrix,宣言为 "defend your app",寓意应该是:当系统受到伤害时,能够像豪猪的棘刺一样保护系统

2. 功能介绍

Hystrix主要提供了以下功能点:

  1. 熔断器(Circuit Breaker)
  2. 隔离(Isolation),提供璧仓模式,实现了线程池隔离和信号量隔离
  3. 回退(fallback),Hystrix会在run()执行过程中出现错误、超时、线程池拒绝、断路器熔断等情况时进行降级处理,有default fallback、单级fallback、多级fallback。
  4. 请求合并(Request Collapsing),@HystrixCollapser,适用于请求的合并,通过指定时间窗口@HystrixProperty(name = "timerDelayInMilliseconds", value = "50")及@HystrixProperty(name = "maxRequestsInBatch", value = "200")来执行批量方法,暂时不展开讲。
  5. 请求缓存(Request Caching)
  6. 仪表盘

Hystrix有两个请求命令 HystrixCommandHystrixObservableCommand

HystrixCommand用在依赖服务返回单个操作结果的时候:

  • execute():同步执行。从依赖的服务返回一个单一的结果对象,或是在发生错误的时候抛出异常。
  • queue():异步执行。直接返回一个Future对象,其中包含了服务执行结束时要返回的单一结果对象。

HystrixObservableCommand用在依赖服务返回多个操作结果的时候:

  • observe():返回Obervable对象,他代表了操作的多个结果,它是一个Hot Observable
  • toObservable():同样返回Observable对象,也代表了操作多个结果,但它返回的是一个Cold Observable。

用法基本

有两种:手动自定义command和使用注解

public class CommandHelloWorld extends HystrixCommand<String> {
    private final String name;
    public CommandHelloWorld(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }
    @Override
    protected String run() throws Exception {
        int i = 1/0;
        return "Hello " + name + "!";
    }
    /**
     * 降级
     * 
     */
    @Override
    protected String getFallback() {
        return "faild";
    }
}
public class ObservableCommandHelloWorld extends HystrixObservableCommand<String> {
    private final String name;
    public ObservableCommandHelloWorld(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }
    @Override
    protected Observable<String> construct() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()) {
                        subscriber.onNext("Hello");
                        int i = 1 / 0; //模拟异常
                        subscriber.onNext(name + "!");
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }
    /**
     * 服务降级
     */
    @Override
    protected Observable<String> resumeWithFallback() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onNext("失败了!");
                        subscriber.onNext("找大神来排查一下吧!");
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }
}
public class CommandHelloWorldTest {
    @Test
    public void testAll() {
        //同步
        new CommandHelloWorld("World").execute();
        //异步
        Future<String> fWorld = new CommandHelloWorld("World").queue();
        //代码1,Hot Observable不论 “事件源” 是否有“订阅者”都会在创建后对事件进行发布。每一个“订阅者”都有可能从“事件源”的中途开始的,并可能只是看到了整个操作的局部过程
        Observable<String> ho = new CommandHelloWorld("World").observe();
        ho.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                System.out.println("call:" + s);
            }
        });
        //代码2,Cold Observable在没有 “订阅者” 的时候并不会发布,而是进行等待,知道有 “订阅者” 之后才发布事件
        Observable<String> co = new CommandHelloWorld("World").toObservable();
        System.out.println(co.toBlocking().single());       
        
        Observable<String> observable= new ObservableCommandHelloWorld("World").observe();
        Iterator<String> iterator = observable.toBlocking().getIterator();
         while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

思考:HystrixCommand已具备了observe()和toObservable()的功能,和HystrixObservableCommand有和不同?

是的,但它的实现有一定的局限性,它返回的Observable只能发射一次数据,而HystrixObservableCommand实现的命令可以获取能发多次的Observable

@HystrixCommand(fallbackMethod = "error")
public String hello() {
    return restTemplate.getForEntity("http://serviceName/hello", String.class).getBody();
}
public String error() {
    //多级降级
    return new FirstLevelFallbackCommand(tag).execute();
}
/**
 * LAZY参数表示使用toObservable()方式执行
 */
@HystrixCommand(observableExecutionMode = ObservableExecutionMode.LAZY, fallbackMethod = "toObserbableError") 
public Observable<String> getUserByName(final String name) {
    return Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            try {
                if(!subscriber.isUnsubscribed()) {
                    subscriber.onNext("找到");
                    subscriber.onNext(name);
                    int i = 1/0; ////抛异常,模拟服务降级
                    subscriber.onNext("了");
                    subscriber.onCompleted();
                }
            } catch (Exception e) {
                subscriber.onError(e);
            }
        }
    });
}
private static class FirstLevelFallbackCommand extends HystrixCommand<String> { 
    private String tag; 
    public FirstLevelFallbackCommand(String tag) { 
	super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("FirstLevelFallbackCommand")));
	this.tag = tag;
    } 
    @Override
    protected String run() throws Exception {
      if ("error".equals(tag)) {
        throw new Exception("一级降级失败,二级降级处理");
      }
      return "成功";
    } 
    @Override
    protected String getFallback() {
      // 实际项目中,通常会在这里做残缺降级。
      System.out.println("二级降级执行成功");
      return "成功";
    } 
}

思考:多级降级的时候,为何将降级command单独做一个线程池?

如果主流程的command都失败了,可能线程池都已经被占满了,降级command必须用自己的独立的线程池。

3. 工作原理

 Hystrix 工作原理,当需要完成某项任务时,通过 Hystrix 将任务包裹起来,交由 Hystrix 来完成任务,从而享受 Hystrix 带来保护。这和古代镖局生意有点类似,将任务委托给镖局,以期安全完成任务。官方 Wiki 中对每一步都做了详细的描述,可以直接参考。下面 流程图 来源于 Hystrix Wiki

3.1 构建命令

前面讲过Hystrix 提供了两个Command,可以使用这两个对象来包裹待执行的任务。 注解@HystrixCommand标记方法,Hystrix 将利用AOP自动将目标方法包装成HystrixCommand来执行,也可以继承他们来创建Command。任务委托给 Hystrix 后,Hystrix 可以应用自己的一系列保护机制,在执行用户任务的各节点(执行前、执行后、异常、超时等)做一系列的事情。

3.2 执行命令

有四种方式执行command:

  • R execute():同步执行,从依赖服务得到单一结果对象,实现为 queue().get()
  • Future queue():异步执行,返回一个 Future 以便获取执行结果,也是单一结果对象,实现为 toObservable().toBlocking().toFuture()
  • Observable observe()hot observable,创建Observable后会订阅Observable,可以返回多个结果
  • Observable toObservable()cold observable,返回一个Observable,只有订阅时才会执行,可以返回多个结果
public R execute() {
    return queue().get();// 利用queue()拿到Future, 执行 get()同步等待拿到执行结果
}
public Future<R> queue() {
    // 实现为 toObservable().toBlocking().toFuture()
    final Future<R> delegate = toObservable().toBlocking().toFuture();
    return delegate;
}
//利用toObservable()得到Observable并直接订阅它,立即执行命令
public Observable<R> observe() {
    ReplaySubject<R> subject = ReplaySubject.create();
    final Subscription sourceSubscription = toObservable().subscribe(subject);
    ...
}

3.3 检查缓存

第3到9步骤构成了 Hystrix 的保护能力,通过这一些列步骤来执行任务,从而起到保护作用。

如果启用了 Hystrix Cache,任务执行前将先判断是否有相同命令执行的缓存。如果有则直接返回缓存的结果;如果没有缓存的结果,但启动了缓存,将缓存本次执行结果以供后续使用。

3.4 断路器是否打开

断路器(circuit-breaker)和保险丝类似,保险丝在发生危险时将会烧断以保护电路,而断路器可以在达到我们设定的阀值时触发短路(比如请求失败率达到50%),拒绝执行任何请求。如果断路器被打开,Hystrix 将不会执行命令,直接进入Fallback处理逻辑。

3.5 检查线程池/信号量情况

Hystrix 隔离方式有线程池隔离和信号量隔离。当使用Hystrix线程池时,Hystrix 默认为每个依赖服务分配10个线程,当10个线程都繁忙时,将拒绝执行命令。信号量同理。

3.6 执行任务

通过HystrixObservableCommand.construct()或者 HystrixCommand.run() 来运行用户真正的任务。

3.7 断路器健康检查

每次开始执行command、结束执行command以及发生异常等情况时,都会记录执行情况,例如:成功、失败、拒绝以及超时等情况,会定期处理这些数据,再根据设定的条件来判断是否开启断路器。

3.8 失败时执行 Fallback

在命令失败时执行用户指定的 Fallback 逻辑。上图中的断路、线程池拒绝、信号量拒绝、执行执行、执行超时都会进入 Fallback 处理。

3.9 返回执行结果

原始结果将以Observable形式返回,在返回给用户之前,会根据调用方式的不同做一些处理。下面是 Hystrix Return flow

4. 源码解析

4.1 HystrixCommandAspect

引入 spring-cloud-starter-hystrix 依赖,spring-cloud-netflix-core 的 jar 包中包含 META-INF/spring.factories 文件(Spring 中也的 Java SPI 的加载机制)。

@Configuration
public class HystrixCircuitBreakerConfiguration {
    public HystrixCircuitBreakerConfiguration() {
    }
    //重要的入口类
    @Bean
    public HystrixCommandAspect hystrixCommandAspect() {
        return new HystrixCommandAspect();
    }
}
@Aspect
public class HystrixCommandAspect {
    @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(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = AopUtils.getMethodFromTarget(joinPoint);
        Validate.notNull(method, "failed to get method from joinPoint: %s", new Object[]{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");
        } else {
            HystrixCommandAspect.MetaHolderFactory metaHolderFactory = (HystrixCommandAspect.MetaHolderFactory)META_HOLDER_FACTORY_MAP.get(HystrixCommandAspect.HystrixPointcutType.of(method));
            MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
            // 创建HystrixInvokable,只是一个空接口,没有任何方法,只是用来标记具备可执行的能力
            HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
            ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ? metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();

            try {
                Object result;
                if (!metaHolder.isObservable()) {
                    // 利用工具CommandExecutor来执行
                    result = CommandExecutor.execute(invokable, executionType, metaHolder);
                } else {
                    result = this.executeObservable(invokable, executionType, metaHolder);
                }

                return result;
            } catch (HystrixBadRequestException var9) {
                throw var9.getCause();
            } catch (HystrixRuntimeException var10) {
                throw this.getCauseOrDefault(var10, var10);
            }
        }
    }
    
}
public class HystrixCommandFactory {
    private static final HystrixCommandFactory INSTANCE = new HystrixCommandFactory();
    private HystrixCommandFactory() {
    }
    public static HystrixCommandFactory getInstance() {
        return INSTANCE;
    }
    public HystrixInvokable create(MetaHolder metaHolder) {
        Object 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 (HystrixInvokable)executable;
    }
}
@ThreadSafe
public class GenericCommand extends AbstractHystrixCommand<Object> {
    private static final Logger LOGGER = LoggerFactory.getLogger(GenericCommand.class);

    public GenericCommand(HystrixCommandBuilder builder) {
        super(builder);
    }
    // 执行具体的方法,如:serviceName的hello
    protected Object run() throws Exception {
        LOGGER.debug("execute command: {}", this.getCommandKey().name());
        return this.process(new AbstractHystrixCommand<Object>.Action() {
            Object execute() {
                return GenericCommand.this.getCommandAction().execute(GenericCommand.this.getExecutionType());
            }
        });
    }
    // 执行fallback方法,如:serviceName的error()
    protected Object getFallback() {
        final CommandAction commandAction = this.getFallbackAction();
        if (commandAction != null) {
            try {
                return this.process(new AbstractHystrixCommand<Object>.Action() {
                    Object execute() {
                        MetaHolder metaHolder = commandAction.getMetaHolder();
                        Object[] args = CommonUtils.createArgsForFallback(metaHolder, GenericCommand.this.getExecutionException());
                        return commandAction.executeWithArgs(metaHolder.getFallbackExecutionType(), args);
                    }
                });
            } catch (Throwable var3) {
                LOGGER.error(FallbackErrorMessageBuilder.create().append(commandAction, var3).build());
                throw new FallbackInvocationException(var3.getCause());
            }
        } else {
            return super.getFallback();
        }
    }
}
public class CommandExecutor {
    // 全文的关键方法
    public static Object execute(HystrixInvokable invokable, ExecutionType executionType, MetaHolder metaHolder) throws RuntimeException {
        Validate.notNull(invokable);
        Validate.notNull(metaHolder);
        switch(executionType) {
        case SYNCHRONOUS:
            // 首先将 invokable 转换为 HystrixExecutable,再执行 HystrixExecutable 的execute() 方法
            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);
        }
    }
    // HystrixExecutable 的 execute() 方法由 HystrixCommand.execute() 实现
    private static HystrixExecutable castToExecutable(HystrixInvokable invokable, ExecutionType executionType) {
        if (invokable instanceof HystrixExecutable) {
            return (HystrixExecutable)invokable;
        } else {
            throw new RuntimeException("Command should implement " + HystrixExecutable.class.getCanonicalName() + " interface to execute in: " + executionType + " mode");
        }
    }
}

HystrixInvokable 也是关键,它的实现类是 GenericCommand 。接下来看看类图,三个抽象父类 AbstractHystrixCommandHystrixCommandAbstractCommand 帮助 GenericCommand 做了不少公共的事情,而 GenericCommand 负责执行具体的方法和fallback时的方法。

本节基本上把目标方法的切入点及执行所需要的关键类一一列举。

4.2 HystrixCommandKey和HystrixCommandGroupKey和HystrixThreadPoolKey

@HystrixCommand(fallbackMethod = "helloFallback", groupKey = "Group1", threadPoolKey = "HystrixFooServiceGaGa")

commandKey:每个command都有对应的commandKey可以认为是command的名字,默认情况下,命令名称来源于类名(getClass().getSimpleName())。自定义使用HystrixCommandKey.Factory.asKey("HelloWorld"),说实话感觉没啥用,不需要自定义。

groupKey:Hystrix使用命令分组将一起的命令进行管理,比如报告、警报、仪表盘或组/库。默认情况下,Hystrix使用 HystrixCommandGroupKey 来定义命令线程池,除非单独定义线程池。

threadPoolKey:线程池主要体现是用于监测、指标发布、缓存和其他此类用途的HystrixThreadPool。

如果同时配置了groupKey 和 threadPoolKey ,那么具有相同的threadPoolKey的使用同一个线程池;

如果只配置了groupKey ,那么具有相同的groupKey 的使用同一个线程池;

《Spring Cloud 微服务实战》推荐:通常情况下,尽量通过 HystrixThreadPoolKey 的方式来指定线程池的划分, 而不是通过组名的默认方式实现划分, 因为多个不同的命令可能 从业务逻辑上来看属于同 一个组, 但是往往从实现本身上需要跟其他命令进行隔离。

4.3 AbstractCommand.toObservable

由于最终入口都是 toObservable(),就从 AbstractCommand的 Observable<R> toObservable() 方法开始。Hystrix 使用观察者模式,Observable 即被观察者,被观察者些状态变更时,观察者可以做出各项响应。因为 Hystrix 基于RxJava,RxJava 不熟悉的童鞋可以参考我之前的分享

abstract class AbstractCommand<R> implements HystrixInvokableInfo<R>, HystrixObservable<R> {
	public Observable<R> toObservable() {
		final AbstractCommand<R> _cmd = this;
		// 命令执行结束后的清理者
		final Action0 terminateCommandCleanup = new Action0() {...};
		// 取消订阅时处理者
		final Action0 unsubscribeCommandCleanup = new Action0() {...};
		// 重点:Hystrix 核心逻辑: 断路器、隔离
		final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {...};
		// 发射数据(OnNext表示发射数据)时的Hook
		final Func1<R, R> wrapWithAllOnNextHooks = new Func1<R, R>() {...};
		// 命令执行完成的Hook
		final Action0 fireOnCompletedHook = new Action0() {...};
		// 通过Observable.defer()创建一个Observable
		return Observable.defer(new Func0<Observable<R>>() {
			@Override
			public Observable<R> call() {
				final boolean requestCacheEnabled = isRequestCachingEnabled();
				final String cacheKey = getCacheKey();
				// 首先尝试从请求缓存中获取结果
				if (requestCacheEnabled) {
					HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
					if (fromCache != null) {
						isResponseFromCache = true;
						return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
					}
				}
				// 使用上面的Func0:applyHystrixSemantics 来创建Observable
				Observable<R> hystrixObservable =
						Observable.defer(applyHystrixSemantics)
								.map(wrapWithAllOnNextHooks);
				Observable<R> afterCache;
				// 如果启用请求缓存,将Observable包装成HystrixCachedObservable并进行相关处理
				if (requestCacheEnabled && cacheKey != null) {
					HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
					...
				} else {
					afterCache = hystrixObservable;
				}
				// 返回Observable
				return afterCache
						.doOnTerminate(terminateCommandCleanup)   
						.doOnUnsubscribe(unsubscribeCommandCleanup)
						.doOnCompleted(fireOnCompletedHook);
			}
		});
	}
}

源码实现比较复杂,可以用一张图解释,这种方式是“军师型”,排兵布阵,先创造了各个处理者,然后创造被观察者,再设置Observable发生各种情况时由谁来处理,完全掌控全局。

解释下Action0、Func1这种对象,他们与Action、Func和Runnable、Callable类似,是一个可以被执行的实体。Action没有返回值,Action0…ActionN表示有0..N个参数,Action0就表示没有参数;Func有返值,0..N一样表示参数。

简单的的来看就是:创建一个Observable,然后绑定各种事件对应的处理者,各类doOnXXXX,表示发生XXX事件时做什么事情。

applyHystrixSemantics

// applyHystrixSemantics 是一个Func0(理解为执行实体或处理者),表示没有参数,返回值是Observable。
final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {
    // Func0 做的事情如下
    @Override
    public Observable<R> call() {
        // 如果未订阅,返回一个"哑炮" Observable, 即一个不会发射任何数据的Observable
        if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {
            return Observable.never();
        }
        // 调用applyHystrixSemantics()来创建Observable
        return applyHystrixSemantics(_cmd);
    }
};

applyHystrixSemantics()

// Semantics 译为语义, 应用Hystrix语义很拗口,其实就是应用Hystrix的断路器、隔离特性
private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {
    // 源码中有很多executionHook、eventNotifier的操作,这是Hystrix拓展性的一种体现。这里面啥事也没做,留了个口子,开发人员可以拓展
    executionHook.onStart(_cmd);
    // 判断断路器是否开启
    if (circuitBreaker.attemptExecution()) {
        // 获取执行信号
        final TryableSemaphore executionSemaphore = getExecutionSemaphore();
        final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
        final Action0 singleSemaphoreRelease = new Action0() {...};
        final Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {...};
        // 判断是否信号量拒绝
        if (executionSemaphore.tryAcquire()) {
            try {
                // 重点:处理隔离策略和Fallback策略
                return executeCommandAndObserve(_cmd)
                        .doOnError(markExceptionThrown)
                        .doOnTerminate(singleSemaphoreRelease)
                        .doOnUnsubscribe(singleSemaphoreRelease);
            } catch (RuntimeException e) {
                return Observable.error(e);
            }
        } else {
            return handleSemaphoreRejectionViaFallback();
        }
    } 
    // 开启了断路器,执行Fallback
    else {
        return handleShortCircuitViaFallback();
    }
}

executeCommandAndObserve()

// 处理隔离策略和各种Fallback
private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
    final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
    final Action1<R> markEmits = new Action1<R>() {...};
    final Action0 markOnCompleted = new Action0() {...};
    // 利用Func1获取处理Fallback的 Observable
    final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {
        @Override
        public Observable<R> call(Throwable t) {
            circuitBreaker.markNonSuccess();
            Exception e = getExceptionFromThrowable(t);
            executionResult = executionResult.setExecutionException(e);
            // 拒绝处理
            if (e instanceof RejectedExecutionException) {
                return handleThreadPoolRejectionViaFallback(e);
            // 超时处理    
            } else if (t instanceof HystrixTimeoutException) {
                return handleTimeoutViaFallback();
            } else if (t instanceof HystrixBadRequestException) {
                return handleBadRequestByEmittingError(e);
            } else {
                ...
                return handleFailureViaFallback(e);
            }
        }
    };
    final Action1<Notification<? super R>> setRequestContext ...
    Observable<R> execution;
    // 利用特定的隔离策略来处理
    if (properties.executionTimeoutEnabled().get()) {
        execution = executeCommandWithSpecifiedIsolation(_cmd)
                .lift(new HystrixObservableTimeoutOperator<R>(_cmd));
    } else {
        execution = executeCommandWithSpecifiedIsolation(_cmd);
    }
    return execution.doOnNext(markEmits)
            .doOnCompleted(markOnCompleted)
            // 绑定Fallback的处理者
            .onErrorResumeNext(handleFallback)
            .doOnEach(setRequestContext);
}

executeCommandWithSpecifiedIsolation()

private Observable<R> executeCommandWithSpecifiedIsolation(final AbstractCommand<R> _cmd) {
    // 线程池隔离
    if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.THREAD) {
        // 再次使用 Observable.defer(), 通过执行Func0来得到Observable
        return Observable.defer(new Func0<Observable<R>>() {
            @Override
            public Observable<R> call() {
                // 收集metric信息
                metrics.markCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.THREAD);
                ...
                try {
                      ... // 获取真正的用户Task
                    return getUserExecutionObservable(_cmd);
                } catch (Throwable ex) {
                    return Observable.error(ex);
                }
                ...
            }
            // 绑定各种处理者
        }).doOnTerminate(new Action0() {...})
            .doOnUnsubscribe(new Action0() {...})
            // 绑定超时处理者
            .subscribeOn(threadPool.getScheduler(new Func0<Boolean>() {
            @Override
            public Boolean call() {
                return properties.executionIsolationThreadInterruptOnTimeout().get() && _cmd.isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT;
            }
        }));
    } 
    // 信号量隔离,和线程池大同小异,全部省略了
    else {
        return Observable.defer(new Func0<Observable<R>>() {...}
    }
}

Observable.defer

defer译为延迟,就是说:必须有观察者订阅时,Observable 才开始发射数据。而defer()的参数是个Func0,是一个会返回Observable的执行实体。

return Observable.defer(new Func0<Observable<R>>() {
    @Override
    public Observable<R> call() {
        // 再一次使用Observable.defer()技能,这次用的是applyHystrixSemantics这个Func0
        Observable<R> hystrixObservable =
                Observable.defer(applyHystrixSemantics)
                        .map(wrapWithAllOnNextHooks);
        ... // 此处忽略了请求缓存处理,上面已有提及
        Observable<R> afterCache;
        ...
        // 为Observable绑定几个特定事件的处理者,这都是上门创建的Action0
        return afterCache
                .doOnTerminate(terminateCommandCleanup) 
                .doOnUnsubscribe(unsubscribeCommandCleanup) 
                .doOnCompleted(fireOnCompletedHook);
    }
});

getUserExecutionObservable()就不接着写了,可以自己看下,就是拿到用户真正要执行的任务。这个任务就是这样被Hystrix包裹着,置于层层防护之下。

猜你喜欢

转载自blog.csdn.net/itsoftchenfei/article/details/85069742