前言
第一章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的关键流程