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,返回來再繼續弄透。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章