springCloud(五)

上一篇,最近加班过于严重,没有时间继续学习,抽了一些零碎的时间,认真的阅读了一下源码和官网的文档,记录一下自己对feign和hystrix的理解。

之前先把feign和hystrix分解的来学,明白了request是如何构造的,请求时如何发送的,接下来整体的进行学习。水平有限,有些理解会有偏差,再深入下去很多概念都不理解了,下一章开始继续学习后面的zuul,把整体的springcloud学完后,再回头深入研究这里和eurake源码。

hystrix把每一次请求都封装成了一个commond对象,实际运行在单独的线程中,也就是设计模式中的命令模式。这也是为什么之前调试源码时一直找不到执行顺序的原因。

springcloud中分别有HystrixCommond和HystrixObservableCommand两个不同的命令对象。

HystrixCommond执行execute()方法,HystrixObservableCommand执行observe()方法。

两个命令的区别在于HystrixCommond的命令逻辑在run方法,HystrixObservableCommand的命令逻辑在construct方法中。

HystrixCommond可以支持同步和异步两种方法,HystrixObservableCommand只支持异步方式。

详细的可以参考stackoverflow的回答:两者的区别

在springcloud中,使用的是HystrixCommond,之前讲过实际去执行请求的是HystrixInvocationHandler类,可以看到invoke的核心逻辑:

HystrixCommand<Object> hystrixCommand = new HystrixCommand<Object>(setterMethodMap.get(method)) {
      @Override
      protected Object run() throws Exception {
        try {
          return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
        } catch (Exception e) {
          throw e;
        } catch (Throwable t) {
          throw (Error) t;
        }
      }

      @Override
      protected Object getFallback() {
        if (fallbackFactory == null) {
          return super.getFallback();
        }
        try {
          Object fallback = fallbackFactory.create(getExecutionException());
          Object result = fallbackMethodMap.get(method).invoke(fallback, args);
          if (isReturnsHystrixCommand(method)) {
            return ((HystrixCommand) result).execute();
          } else if (isReturnsObservable(method)) {
            // Create a cold Observable
            return ((Observable) result).toBlocking().first();
          } else if (isReturnsSingle(method)) {
            // Create a cold Observable as a Single
            return ((Single) result).toObservable().toBlocking().first();
          } else if (isReturnsCompletable(method)) {
            ((Completable) result).await();
            return null;
          } else {
            return result;
          }
        } catch (IllegalAccessException e) {
          // shouldn't happen as method is public due to being an interface
          throw new AssertionError(e);
        } catch (InvocationTargetException e) {
          // Exceptions on fallback are tossed by Hystrix
          throw new AssertionError(e.getCause());
        }
      }
    };

重写了run和getFallback方法,run方法就是命令的执行逻辑,getFallback就是出现异常或者开启熔断时的降级处理方法。




dispatch中的key就是待执行的feign远程调用方法,value就是我们之前学到的SynchronousMethodHandler对象,包括了target好额构造的request。

构造完HystrixCommond对象后,调用execute方法:

  public R execute() {
        try {
            return queue().get();
        } catch (Exception e) {
            throw decomposeException(e);
        }
    }


该方法是同步执行的,实际上顺序执行queue和get两个方法,queue方法核心如下:

final Observable<R> o = toObservable();
        final Future<R> f = o.toBlocking().toFuture();

queue实际上是异步的,看toObservable()方法的解释:

Used for asynchronous execution of command with a callback by subscribing to the {@link Observable}.

这里实际上就是观察者模式,只有当有订阅了该对象时才会执行,toObservable()方法的主要逻辑:

首先查询缓存:

 if (requestCacheEnabled) {
            Observable<R> fromCache = requestCache.get(getCacheKey());
            if (fromCache != null) {
                /* mark that we received this response from cache */
                metrics.markResponseFromCache();
                isExecutionComplete.set(true);
                try {
                    executionHook.onCacheHit(this);
                } catch (Throwable hookEx) {
                    logger.warn("Error calling HystrixCommandExecutionHook.onCacheHit", hookEx);
                }
                return new CachedObservableResponse<R>((CachedObservableOriginal<R>) fromCache, this);
            }
        }


缓存中没有则创建一个被观察者对象,等待有订阅时执行命令,主要就是构造对象,重写call方法,其中会有一些记录统计信息的操作。

 Observable<R> o = Observable.create(new OnSubscribe<R>() ;
然后根据需求再把对象缓存。

创建了被观察对象之后,接下来就是订阅该对象,就可以执行方法,实现一个假的同步方法了。

实际上执行的逻辑就在toFuture中,至此,hystrix就利用异步的方法伪造了一个同步执行的逻辑。


接着看一下当远程的方法抛异常时,是如何进入fallback的。

首先又回到了之前学过的SynchronousMethodHandler,这里是真正进行请求和解析返回的地方。

当请求返回异常时,

throw errorDecoder.decode(metadata.configKey(), response);

抛出该异常,在HystrixCommond的run方法中捕获该异常后直接抛出


后进入:

final protected Observable<R> getFallbackObservable() {
        return Observable.create(new OnSubscribe<R>() {

            @Override
            public void call(Subscriber<? super R> s) {
                try {
                    s.onNext(getFallback());
                    s.onCompleted();
                } catch (Throwable e) {
                    s.onError(e);
                }
            }

        });
    }

进入到了上面我们重写的getFallBack中,

Object fallback = fallbackFactory.create(getExecutionException());
          Object result = fallbackMethodMap.get(method).invoke(fallback, args)


利用反射执行我们的fallbackfactory。


下一篇不再研究这里的源码了,超出能力范围太多,先学习zuul,返回来再继续弄透。




发布了45 篇原创文章 · 获赞 21 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ly262173911/article/details/77623626