Hystrix源码阅读(一)HystrixCommand的四种执行方式

4,129 阅读2分钟

前言

第一章Hystrix源码阅读,先看一下执行HystrixCommand的四种方式,如上图。

一、HystrixCommand.execute

  • execute同步执行。案例如下:
private <T> HystrixCommand<T> createCommand(T message) {
      HystrixCommand.Setter setter = HystrixCommand.Setter
              .withGroupKey(HystrixCommandGroupKey.Factory.asKey("serviceA"))
              .andCommandKey(HystrixCommandKey.Factory.asKey("methodA"));
      return new HystrixCommand<T>(setter) {
          @Override
          protected T run() throws Exception {
              System.out.println("HystrixCommand执行了!!!");
              return message;
          }
      };
  }
@Test
public void test01() {
    HystrixCommand<String> command = createCommand("this is test01");
    System.out.println(command.execute());
}
  • HystrixCommand的execute方法实际是调用了queue
public R execute() {
    return queue().get();
}

二、HystrixCommand.queue

  • queue异步执行,返回一个Future。案例如下:
@Test
public void test02() throws ExecutionException, InterruptedException {
    HystrixCommand<String> command = createCommand("this is test02");
    Future<String> f = command.queue();
    System.out.println("queue之后,command就执行了");
    Thread.sleep(1000);
    System.out.println(f.get());
}
  • HystrixCommand的queue方法实际是调用了toObservable
// 标志位 标识future被取消后,执行线程是否被中断
private final AtomicBoolean interruptOnFutureCancel = new AtomicBoolean(false);
public Future<R> queue() {
		// toObservable转换为Observable
        // toBlocking转换为BlockingObservable
        // toFuture转换为Future
        // 完成了Observable的创建和订阅
        final Future<R> delegate = toObservable().toBlocking().toFuture();
        // 代理future,对于cancel操作做特殊处理
        // 因为toObservable().toBlocking().toFuture()返回的future无法通过cancel方法中断执行线程。
        final Future<R> f = new Future<R>() {
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                if (delegate.isCancelled()) {
                    return false;
                }
                // 如果 execution.isolation.thread.interruptOnFutureCancel = true(默认false)
                if (HystrixCommand.this.getProperties()
                .executionIsolationThreadInterruptOnFutureCancel().get()) {
                	// 设置标志位
                    interruptOnFutureCancel.compareAndSet(false, mayInterruptIfRunning);
        		}
                // 执行目标future的cancel
                final boolean res = delegate.cancel(interruptOnFutureCancel.get());
                // 如果command还没执行完成 且 需要中断执行的线程
                if (!isExecutionComplete() && interruptOnFutureCancel.get()) {
                	// 获取执行线程
                    final Thread t = executionThread.get();
                    // 执行线程非当前线程则中断线程
                    if (t != null && !t.equals(Thread.currentThread())) {
                        t.interrupt();
                    }
                }
                return res;
			}
        	// ... 其他方法使用delegate正常逻辑重写
        };
        // 如果执行完毕
		if (f.isDone()) {
            try {
                f.get();
                return f;
            } catch (Exception e) {
                // 异常处理...
            }
        }
        return f;
    }

三、HystrixCommand.observe

  • observe方法返回一个Hot Observable,因为observe方法调用后HystrixCommand就执行了(异步),通过subscribe订阅返回的Observable获取处理结果。案例如下:
@Test
public void test03() throws InterruptedException {
    HystrixCommand<String> command = createCommand("this is test03");
    Observable<String> observe = command.observe();// observe直接执行run方法,称为Hot Observable
    System.out.println("observe之后,command就执行了");
    Thread.sleep(1000);
    observe.subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            System.out.println("通过订阅,获取执行结果:" + s);
        }
    });
}
// 控制台:
// observe之后,command就执行了
// HystrixCommand执行了!!!
// 通过订阅,获取执行结果:this is test03
  • HystrixCommand的observe方法实际是调用了toObservable,并且直接subscribe订阅了
 public Observable<R> observe() {
    ReplaySubject<R> subject = ReplaySubject.create();
    final Subscription sourceSubscription = toObservable().subscribe(subject);
    return subject.doOnUnsubscribe(new Action0() {
        @Override
        public void call() {
            sourceSubscription.unsubscribe();
        }
    });
}

四、HystrixCommand.toObservable

  • toObservable方法返回一个Cold Observable,因为HystrixCommand的run方法这里在调用toObservable不会立即执行,run方法需要订阅后执行。案例如下:
@Test
public void test04() throws InterruptedException {
    HystrixCommand<String> command = createCommand("this is test04");
    Observable<String> observe = command.toObservable();// toObservable不直接执行run方法
    System.out.println("未订阅,command不执行");
    Thread.sleep(1000);
    System.out.println("订阅后,command执行了");
    observe.subscribe();
    Thread.sleep(1000);
}
// 控制台:
// 未订阅,command不执行
// 订阅后,command执行了
// HystrixCommand执行了!!!

总结

  • HystrixCommand的四种执行方式
方法同步/异步返回值
execute同步T
queue异步Future<T>
observe异步Observable<T>
toObservable未执行Observable<T>
  • HystrixCommand的四种执行方式的底层都是toObservable方法,而HystrixCommand.toObservable方法是Hystrix的关键流程