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);
}
}
- ribbon追求爲每個服務獨立配置負載均衡策略,所以每個服務都有自己的IClientConfig實例。
- 從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