Hystrix框架初探
一、RxJava简单接触
之前就看过一下Hystrix框架,但是碍于RxJava语法太绕,一直也没看下去,这样总感觉跟Hystrix隔着一层纱,今天抽时间先简单过下了RxJava,几个重要的对象如下:
1、Observable:事件生产者/被观察者
2、Observer/Subscriber:观察者/订阅者
RxJava的整体思路是生产者生产事件由订阅者来消费,下面是简单的使用例子1:
1、定义观察者
//观察者
Observer observer=new Observer()
{
//完成时触发
public void onCompleted() {
System.out.println(Thread.currentThread().getName() +"观察者事件完成");
}
//出错时触发
public void onError(Throwable e) {
System.out.println(Thread.currentThread().getName() +"观察者事件出错");
}
//每接收一次事件 触发一次
public void onNext(Object o) {
System.out.println(Thread.currentThread().getName() +"观察者接收到事件,数据为:"+o);
}
};
2、定义订阅者,订阅者是高级一点的观察者,比观察者多一些功能而已,所以只需要定义其中一个就好
//订阅者
Subscriber subscriber=new Subscriber()
{
@Override
public void onStart() {
super.onStart();
System.out.println(Thread.currentThread().getName() +"事件发生之前发生");
}
//完成时触发
public void onCompleted() {
System.out.println(Thread.currentThread().getName() +"订阅者事件完成");
}
//出错时触发
public void onError(Throwable e) {
System.out.println(Thread.currentThread().getName() +"订阅者事件出错");
}
//每接收一次事件 触发一次
public void onNext(Object o) {
System.out.println(Thread.currentThread().getName() +"订阅者接收到事件,数据为:"+o);
}
};
3、定义生产者
//生产者
Observable observable=Observable.create(new Observable.OnSubscribe<String>(){
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext(Thread.currentThread().getName() + "生产者触发事件");
subscriber.onCompleted();
}
});
4、当有了生产者和消费者,怎么让他们直接关联了,当然是subscribe方法,订阅
observable.subscribe(subscriber);//subscriber这里也可以是observer
这样最后输出结果就是
main事件发生之前发生 main订阅者接收到事件,数据为:main生产者触发事件 main订阅者事件完成
上面就是RxJava一个简单的例子,但是看起来还挺麻烦,不过RxJava的函数式变成可不只是这样,再看如下例子2:
Observable.create(new Observable.OnSubscribe<String>(){
public void call(Subscriber<? super String> subscriber) {
System.out.println(Thread.currentThread().getName() + "生产者触发事件");
subscriber.onNext("100");
subscriber.onCompleted();
}
}).map(new Func1<String,Integer>(){
public Integer call(String s) {
return Integer.valueOf(s);
}
}).subscribe(new Subscriber<Integer>() {
public void onCompleted() {
System.out.println(Thread.currentThread().getName() + "订阅者完成");
}
public void onError(Throwable e) {
System.out.println(Thread.currentThread().getName() + "订阅者出错");
}
public void onNext(Integer s) {
System.out.println(Thread.currentThread().getName() + "订阅者事件触发:"+(s+10));
}
});
例子2看起来简洁很多但是实际比例子1只是多了map操作符,方便对事件流过程种的数据进行加工。RxJava有相当多的操作符,可以简单的概括如下:

下面回归到今天的重点,Hystrix
二、Hystrix执行过程分析
Hystrix有三种执行方式:同步执行、异步执行、响应式执行。
下面我们简单的从同步执行来分析,例子3如下:
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() {
// a real example would do work like a network call here
return "Hello " + name + "!";
}
}
同步执行调用代码:
String s = new CommandHelloWorld("World").execute();
下面我们重点分析execute方法:
public R execute() {
try {
return queue().get();//这里面其实也是使用的异步方法,再同步获取结果
} catch (Exception e) {
throw Exceptions.sneakyThrow(decomposeException(e));
}
}
这里我们再分析queue()方法:
public Future<R> queue() {
final Future<R> delegate = toObservable().toBlocking().toFuture();
final Future<R> f = new Future<R>() {
......
@Override
public boolean isDone() {
return delegate.isDone();
}
@Override
public R get() throws InterruptedException, ExecutionException {
return delegate.get();
}
......
};
return f;
}
这里面最核心的就是toObservable().toBlocking().toFuture()把观察者转换为Future对象,我们先看toObservable方法:
public Observable<R> toObservable() {
final AbstractCommand<R> _cmd = this;
final Action0 terminateCommandCleanup = new Action0() {
@Override
public void call() {
...
}
};
//mark the command as CANCELLED and store the latency (in addition to standard cleanup)
final Action0 unsubscribeCommandCleanup = new Action0() {
@Override
public void call() {
...
}
};
final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {
@Override
public Observable<R> call() {
if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {
return Observable.never();
}
return applyHystrixSemantics(_cmd);
}
};
final Action0 fireOnCompletedHook = new Action0() {
@Override
public void call() {
...
}
};
return Observable.defer(new Func0<Observable<R>>() {
@Override
public Observable<R> call() {
commandStartTimestamp = System.currentTimeMillis();
Observable<R> hystrixObservable =
Observable.defer(applyHystrixSemantics)
.map(wrapWithAllOnNextHooks);
Observable<R> afterCache;
if (requestCacheEnabled && cacheKey != null) {
} else {
afterCache = hystrixObservable;
}
return afterCache
.doOnTerminate(terminateCommandCleanup)
.doOnUnsubscribe(unsubscribeCommandCleanup)
.doOnCompleted(fireOnCompletedHook);
}
});
}
这个方法看起来很复杂,但是把无关流程的代码去掉之后,核心的就是bservable.defer()方法里面先判断了是否走缓存逻辑,然后重新包装了Observable对象返回,defer()需要的是Func0<Observable<T>>对象,作用是当调用订阅方法时会触发Func0对象的call方法。
然后我们重点关注的时hystrixObservable的创建,我们可以看到也是调用了defer方法,里面使用的是applyHystrixSemantics对象,真正会调用的是call方法中的applyHystrixSemantics(_cmd)这个方法,传入了当前命令,剥开层层包装,终于找到真正的调用入口。
private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {
executionHook.onStart(_cmd);
//熔断器是否允许继续执行
if (circuitBreaker.allowRequest()) {
//获取当前信号量
final TryableSemaphore executionSemaphore = getExecutionSemaphore();
final Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {
@Override
public void call(Throwable t) {
eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, commandKey);
}
};
//如果还能获取,就继续往下执行
if (executionSemaphore.tryAcquire()) {
executionResult = executionResult.setInvocationStartTime(System.currentTimeMillis());
return executeCommandAndObserve(_cmd)
.doOnError(markExceptionThrown)
.doOnTerminate(singleSemaphoreRelease)
.doOnUnsubscribe(singleSemaphoreRelease);
} else {
//直接返回信号量限制结果
return handleSemaphoreRejectionViaFallback();
}
} else {
//直接返回熔断结果
return handleShortCircuitViaFallback();
}
}
这个方法主要检查了熔断器和信号量,然后下一步会走executeCommandAndObserve方法:
private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
final Action1<R> markEmits = new Action1<R>() {
@Override
public void call(R r) {
...
}
};
final Action0 markOnCompleted = new Action0() {
@Override
public void call() {
...
}
};
//降级处理
final Func1<Throwable, Observable<R>> handleFallback = new Func1<Throwable, Observable<R>>() {
@Override
public Observable<R> call(Throwable t) {
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 {
/*
* Treat HystrixBadRequestException from ExecutionHook like a plain HystrixBadRequestException.
*/
if (e instanceof HystrixBadRequestException) {
eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
return Observable.error(e);
}
return handleFailureViaFallback(e);
}
}
};
final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() {
@Override
public void call(Notification<? super R> rNotification) {
setRequestContextIfNeeded(currentRequestContext);
}
};
Observable<R> execution;
//启用了超时
if (properties.executionTimeoutEnabled().get()) {
//lift会包装超时操作
execution = executeCommandWithSpecifiedIsolation(_cmd)
.lift(new HystrixObservableTimeoutOperator<R>(_cmd));
} else {
execution = executeCommandWithSpecifiedIsolation(_cmd);
}
return execution.doOnNext(markEmits)
.doOnCompleted(markOnCompleted)
.onErrorResumeNext(handleFallback)//
.doOnEach(setRequestContext);
}
上面我们可以看到executeCommandAndObserve又重新包装了Observable对象,包含超时、降级逻辑,接下来我们主要看executeCommandWithSpecifiedIsolation方法,看名称我们就能知道是执行带有指定隔离的命令。
未完,待续...

浙公网安备 33010602011771号