SpringCloud源碼研讀(四):ribbon

Ribbon運行時Bean做了命名空間隔離,給每個服務方定義一個獨立的bean上下文。這樣做是爲了支持對某一個服務單獨配置負載。比如負載算法,是否重試等,也可以爲每一個服務實例化一個服務發現邏輯,可以最大化地將自由交給實現方。

核心領域對象

  • SpringClientFactory是Ribbon全局唯一的bean工廠,只有一個實例。通過getInstances(String name, Class type)可以創建不同的命名空間(name)的不同類型對象(type)實例。

  • 對@FeignClient聲明的服務而言,每一個name都有一個FeignLoadBalancer實例。FeignLoadBalancer通過DynamicServerListLoadBalancer執行具體的負載均衡工作。

  • DynamicServerListLoadBalancer承載了Ribbon運行時負載均衡的全部邏輯,包括負載選擇,重試等等。

  • ConsulServerList是一個邏輯含義的服務,指向一組具有相同業務功能的物理服務。是負載均衡選擇的基礎。

  • ConsulServer是一個物理含義的服務,指向服務的一個具體的運行實例。

[外鏈圖片轉存失敗(img-0C6sZO82-1566033499215)(C:\work\springcloud\out\robbin\doc\core\robbin.png)]

bean註冊

Ribbon註冊的引入鏈爲

RibbonAutoConfiguration
   => SpringClientFactory
   => @RibbonClients
      => RibbonClientConfigurationRegistrar

SpringClientFactory懶加載

Ribbon運行時依賴的類並沒有在spring Application啓動時初始化,而是在使用時懶加載。在需要時,SpringClientFactory基於RibbonClientConfiguration創建對應的bean實例。SpringClientFactory繼承了NamedContextFactory。

Feign運行時,SynchronousMethodHandler.executeAndDecode(RequestTemplate)調用LoadBalancerFeignClient實現負載均衡。分析LoadBalancerFeignClient代碼可以看出懶加載的過程:

//LoadBalancerFeignClient
@Override
public Response execute(Request request, Request.Options options) throws IOException {
	try {
		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);
//1. 懶加載IClientConfig
		IClientConfig requestConfig = getClientConfig(options, clientName);
		return lbClient(clientName) //2. 懶加載FeignLoadBalancer
				.executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse();
	}
	catch (ClientException e) {
		IOException io = findIOException(e);
		if (io != null) {
			throw io;
		}
		throw new RuntimeException(e);
	}
}
  1. ribbon追求爲每個服務獨立配置負載均衡策略,所以每個服務都有自己的IClientConfig實例。
  2. 從CachingSpringLoadBalancerFactory獲取FeignLoadBalancer,沒有會從SpringClientFactory創建。

SpringClientFactory創建ILoadBalancer時調用堆棧:

RibbonClientConfiguration.ribbonLoadBalancer(IClientConfig,ServerList,ServerListFilter,IRule,IPing,ServerListUpdater) 
ZoneAwareLoadBalancer.<init>(IClientConfig,IRule,IPing,ServerList,ServerListFilter,ServerListUpdater) 
DynamicServerListLoadBalancer.<init>(IClientConfig,IRule,IPing,ServerList,ServerListFilter,ServerListUpdater) 
ConsulServerList.getUpdatedListOfServers()
ConsulServerList.getServers()
ConsulClient.getHealthServices(String,String,boolean,QueryParams,String) 
HealthConsulClient.getHealthServices(String,String,boolean,QueryParams,String)
ConsulRawClient.makeGetRequest(String,UrlParameters[]) 

在創建DynamicServerListLoadBalancer時,Ribbon會調用consul server查詢service的實例信息。同時創建心跳檢測ServerListUpdater。

運行時調用

DynamicServerListLoadBalancer在運行時執行負載均衡策略。
在這裏插入圖片描述

負載均衡策略

負載均衡策略由IRule執行。
在這裏插入圖片描述

健康檢查

PollingServerListUpdater定期查詢consul server檢查service的各實例健康情況。

Ribbon和Spring Cloud Consul: http://blog.sina.com.cn/s/blog_72ef7bea0102xft7.html

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