<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      前言

      書接上文,feign接口是如何注冊到容器想必已然清楚,現在我們著重關心一個問題,feign調用服務的時候是如何抉擇的?上一篇主要是從讀源碼的角度入手,后續將會逐步從軟件構架方面進行剖析。

      一、ReflectiveFeign.FeignInvocationHandler

      從上文知道feign接口調用實質上是調用的對應的動態代理接口的InvocationHandler,跟蹤源碼發現默認的InvocationHandler實現就是FeignInvocationHandler。現在我們看一下這個FeignInvocationHandler.invoke(...)方法。

      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("equals".equals(method.getName())) {
              try {
                Object otherHandler =
                    args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                return equals(otherHandler);
              } catch (IllegalArgumentException e) {
                return false;
              }
            } else if ("hashCode".equals(method.getName())) {
              return hashCode();
            } else if ("toString".equals(method.getName())) {
              return toString();
            }
            // dispath 是緩存的method 以及 method對應的MethodHandler
            return dispatch.get(method).invoke(args);
          }
      
      

      從代碼中可以看到他是直接從緩存中拿到對應的MethodHandler,然后調用的MethodHandler的invoke方法。我們看一下MethodHandler都有哪些實現:

      可以看到就兩個實現, DefaultMethodHandler處理的是feign接口中的Default修飾的方法。我們調用的遠程接口用的是SynchronousMethodHandler實現。那么可以看到我們最終對feing接口的某個方法的調用實際上調用的是SynchronousMethodHandler.invoke(...)方法。跟蹤代碼發現,最終調用的是SynchronousMethodHandler持有的Client的實例的execute方法。那么我們看一下Client都有那些實現:

      這里跟蹤SynchronousMethodHandler的創建過程發現Client的創建是按照如下邏輯進行的(FeignClientFactoryBean.loadBalance):

      
      protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
      			HardCodedTarget<T> target) {
      		Client client = getOptional(context, Client.class);
      		if (client != null) {
      			builder.client(client);
      			Targeter targeter = get(context, Targeter.class);
      			return targeter.target(this, builder, context, target);
      		}
      
      		throw new IllegalStateException(
      				"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
      	}
      
      

      從上述代碼可以看到,他從context中獲取到client,然后通過client獲取執行。想必feign肯定是自動裝備了一個Client,我們看一下他的默認配置:

      顯然配置必定是從FeignAutoConfiguration 或者 FeignRibbonClientAutoConfiguration進行配置的,查看這兩個類最終發現Client是通過FeignRibbonClientAutoConfiguration進行注入的(通過@Import引入的DefaultFeignLoadBalancedConfiguration進行注入):

      
      @Configuration
      class DefaultFeignLoadBalancedConfiguration {
      
      	@Bean
      	@ConditionalOnMissingBean
      	public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
      			SpringClientFactory clientFactory) {
      		return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory,
      				clientFactory);
      	}
      
      }
      

      所以我們調用feign接口的某一個方法,最終調用的LoadBalancerFeignClient.execute()方法。那么負載均衡相關邏輯應該是在此接入的。

      二、LoadBalancerFeignClient 做了些什么

      先看核心代碼,注意注釋部分:

      
      public Response execute(Request request, Request.Options options) throws IOException {
      		try {
                              // URL 處理  
      			URI asUri = URI.create(request.url());
      			String clientName = asUri.getHost();
      			URI uriWithoutHost = cleanUrl(request.url(), clientName);
      			FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
      					this.delegate, request, uriWithoutHost);
                              // 獲取調用服務配置
      			IClientConfig requestConfig = getClientConfig(options, clientName);
      
                              // 創建負載均衡客戶端,執行請求
      			return lbClient(clientName)
      					.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
      		}
      		catch (ClientException e) {
      			IOException io = findIOException(e);
      			if (io != null) {
      				throw io;
      			}
      			throw new RuntimeException(e);
      		}
      	}
      
      

      從上面的代碼可以看到,lbClient(clientName) 創建了一個負載均衡的客戶端,它實際上就是生成的如下所述的類:

      
      public class FeignLoadBalancer extends
      		AbstractLoadBalancerAwareClient<FeignLoadBalancer.RibbonRequest, FeignLoadBalancer.RibbonResponse> 
      
      

      熟悉ribbon的朋友應該知道AbstractLoadBalancerAwareClient 就是Ribbon負載均衡調用的父類。具體的負載均衡實現策略,下一章在詳細描述。至此我們可以得出結論:feign集成負載均衡是通過將FeignLoadBalancer作為調用feign接口的實際執行者,從而達到負載均衡的效果。可以看到這里與Ribbon高度的解耦,相當于我們獲取了服務名、調用地址、調用參數后,最終交由一個執行器去調用。執行器并不關心參數從何而來,這里基于Ribbon提供的執行器實現只是更具傳遞的服務名找到了一個正確的實例去調用而已。

      三 、 小結

      至此我們可以看到初步職責劃分: 代理對象、請求與響應解析、執行器三個職能部門。

      • 代理對象職責是: 將feign接口中方法的調用轉接到對FeignInvocationHandler的invoke調用,在invoke函數中通過方法名稱找到對應的SynchronousMethodHandler。
      • 執行器: 負責根據請求的方法解析出調用信息(調用服務名、調用地址、調用參數)然后發起調用,他不關心參數是如何來的

      一個系統的好壞、可擴展性高低很大程序上取決于系統中各職能部門劃分是否清晰以及各個職能部分的權限是否越界。

      posted on 2020-10-12 18:07  泥粑  閱讀(1838)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 午夜福利院一区二区三区| 日韩成人午夜精品久久高潮| 婷婷色婷婷深深爱播五月| 久久香蕉国产线看观看怡红院妓院| 欧美人与动交视频在线观看| 成人国产av精品免费网| 欧美激情一区二区久久久| 干老熟女干老穴干老女人| 国产福利视频区一区二区| 最近中文字幕日韩有码| 彝良县| 熟女国产精品一区二区三| 亚洲一区久久蜜臀av| 色噜噜在线视频免费观看| 日本高清在线观看WWW色| 邯郸市| 一区二区三区四区五区自拍| 欧美白妞大战非洲大炮| 国产精品国三级国产av| 97一期涩涩97片久久久久久久| 老熟妇性老熟妇性色| 亚洲精品成人一二三专区| 精品无码一区二区三区的天堂| av无码精品一区二区乱子| 国产精品不卡一区二区在线| 成人午夜免费无码视频在线观看 | 少妇激情av一区二区三区| 国产在线视频www色| 亚洲一区二区av观看| 国产中文字幕在线精品| 中文字幕在线视频不卡一区二区 | 青青草国产精品日韩欧美| 亚洲乱码精品久久久久..| 国产av一区二区三区精品| 蜜臀av在线观看| 久久AV中文综合一区二区| 国产偷国产偷亚洲清高动态图| 国产一区二区三区尤物视频| 日韩国产精品中文字幕| 国产AV午夜精品一区二区三区 | 国产精品视频中文字幕|