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号