客戶端負載均衡 Spring Cloud Ribbon
Spring Cloud Ribbon是一個基于HTTP和TCP的客戶端負載均衡工具,它基于Netflix Ribbon實現(xiàn)逊拍,可以將面向服務(wù)的REST模板請求自動轉(zhuǎn)換為客戶端負載均衡的服務(wù)調(diào)用交胚。
1. 客戶端負載均衡
負載均衡在系統(tǒng)架構(gòu)中是一個非常重要且不得不去實施的內(nèi)容。負載均衡是對系統(tǒng)的高可用绊起,網(wǎng)絡(luò)壓力的緩解和處理能力的擴容的重要手段之一精拟。通常所說的負載均衡是指服務(wù)端負載均衡,而客戶端負載均衡和服務(wù)端負載均衡最大的不同點在于服務(wù)清單所存儲的位置虱歪。在客戶端負載均衡中蜂绎,所有的客戶端節(jié)點都維護著自己要訪問的服務(wù)端清單,也需要心跳去維護服務(wù)端清單的健康性实蔽,只是需要與注冊中心配合完成荡碾。
1.1 使用客戶端負載均衡調(diào)用
- 服務(wù)提供者啟動多個服務(wù)實例并注冊到一個或多個相關(guān)聯(lián)的服務(wù)注冊中心
@Bean
@LoadBelanced
RestTemplate restTemplate() {
return new RestTemplate();
}
- 服務(wù)消費者通過調(diào)用被
@LoadBalanced
注解修飾的RestTemplate來實現(xiàn)面向服務(wù)的接口調(diào)用
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET)
public String helloConsumer() {
return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody();
}
1.2 RestTemplate詳解
RestTemplate對象會使用Ribbon的自動化配置,同時通過配置@LoadBalanced
開啟客戶端的負載均衡局装。
RestTemplate針對不同請求類型和參數(shù)類型的服務(wù)調(diào)用實現(xiàn)請參見JDK文檔坛吁。
2. 負載均衡策略及配置
2.1 負載均衡策略
在Ribbon中實現(xiàn)了非常多的選擇策略(IRule接口的各個實現(xiàn))
- RandomRule:隨機選擇策略
該策略實現(xiàn)了從服務(wù)實例清單中隨機選擇一個服務(wù)實例,具體的選擇邏輯在一個while(server == null)循環(huán)之內(nèi)铐尚,若出現(xiàn)死循環(huán)獲取不到服務(wù)實例時拨脉,很有可能存在并發(fā)的bug。 - RoundRobinRule:線性輪詢選擇策略
該策略實現(xiàn)了按照線性輪詢的方式依次選擇每個服務(wù)實例宣增,與隨機策略除獲取實例邏輯不同外玫膀,在循環(huán)條件中新增一個計數(shù)器,當一直獲取不到實例超過10次就會結(jié)束嘗試爹脾。而線性輪詢的實現(xiàn)是通過AtomicInteger nextServerCyclicCounter
對象實現(xiàn)帖旨,每次進行實例選擇時調(diào)用incrementAndGetModulo
函數(shù)實現(xiàn)遞增箕昭。 - RetryRule:具備重試機制的選擇策略
該策略實現(xiàn)了一個具備重試機制的實例選擇,在其內(nèi)部定義了一個IRule對象解阅,默認使用了RoundRobinRule選擇策略落竹。實現(xiàn)了對內(nèi)部選擇策略進行反復嘗試的策略,若期間能選擇到具體服務(wù)實例就返回货抄,否則根據(jù)根據(jù)設(shè)置的嘗試結(jié)束時間為閾值(maxRetryMills參數(shù)定義的值 + choose方法開始執(zhí)行的時間戳)述召,當超過該閾值返回null。 - WeightResponseTimeRule:加權(quán)選擇策略
該策略是對RoundRobinRule的擴展蟹地,增加了根據(jù)實例的運行情況來計算權(quán)重积暖,并根據(jù)權(quán)重來挑選實例,它的實現(xiàn)主要有三個核心內(nèi)容怪与。- 定時任務(wù):WeightResponseTimeRule策略在初始化的時候會啟動一個定時任務(wù)夺刑,用來為每個服務(wù)實例計算權(quán)重,該任務(wù)默認每30秒執(zhí)行一次
- 權(quán)重計算:通過maintainWeights函數(shù)實現(xiàn)琼梆。先根據(jù)LoadBalancerStats記錄每個實例的統(tǒng)計信息性誉,累加所有實例的平均響應(yīng)時間得到總平均響應(yīng)時間totalResponseTime,再為實例清單逐個計算權(quán)重茎杂,規(guī)則為 weightSoFar + totalResponseTime - 實例平均響應(yīng)時間错览,其中weightSoFar初始化為0,且每計算好幾個權(quán)重需要累加到weightSoFar上供下一次計算使用煌往。需要注意的是權(quán)重值只是表示各實例的權(quán)重區(qū)間倾哺,并非每個實例的優(yōu)先級,因此不是數(shù)值越大選中概率越大刽脖。
- 實例選擇:生成[0, 最大權(quán)重值)區(qū)間的隨機數(shù)羞海,遍歷權(quán)重列表,若權(quán)重值大于等于隨機數(shù)則用當前權(quán)重列表的索引獲取服務(wù)實例曲管。
- BestAvailableRule:最空閑連接
該策略利用LoadBalancerStats中保存的實例統(tǒng)計信息却邓,通過遍歷負載均衡器中維護的所有服務(wù)實例,過濾故障的實例并找出請求數(shù)最小的實例院水。
2.2 負載均衡配置
2.2.1 自動化配置
? 在引入Spring Cloud Ribbon依賴后腊徙,構(gòu)建以下接口的實現(xiàn)
interface | description | default |
---|---|---|
IClientConfig | Ribbon客戶端配置 | com.netflix.client.config.DefaultClientConfigImpl |
IRule | Ribbon負載均衡策略 | com.netflix.loadbalancer.ZoneAvoidanceRule |
IPing | Ribbon實例檢查策略 | com.netflix.loadbalancer.NoOpPing |
ServerList<Server> | 服務(wù)實例清單維護機制 | com.netflixloadbalancer.ConfigurationBasedServerList |
ServerListFilter<Server> | 服務(wù)實例清單過濾機制 | org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter |
ILoadBalancer | 負載均衡器 | com.netflix.loadbalancer.ZoneAwareLoadBalancer |
修改Ribbon實例檢查策略示例
@Configuration
public class MyRibbonConfiguration {
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
}
2.2.2 Camden版本對RibbonClient配置優(yōu)化
在Camden版本中,Spring Cloud Ribbon對RibbonClient定義個性化配置的方法做了進一步優(yōu)化檬某∏颂冢可以直接通過<clientName>.ribbon.<key>=<value>的形式進行配置(<clientName>.可省略表示全局配置)。配置名配置的對應(yīng)接口
key | description |
---|---|
NFLoadBalancerPingClassName | 配置IPing接口的實現(xiàn) |
NFLoadBalancerClassName | 配置ILoadBalancer接口的實現(xiàn) |
NFLoadBalancerRuleClassName | 配置IRule接口的實現(xiàn) |
NIWSServerListClassName | 配置ServerList接口的實現(xiàn) |
NIWSServerListFilterClassName | 配置ServerListFilter接口的實現(xiàn) |
修改Ribbon實例檢查策略示例
服務(wù)名.ribbon.NFLoadBalancerPingClassName=com.netflix.loadbalancer.PingUrl
2.2.3 與Eureka結(jié)合
當在Spring Cloud的應(yīng)用中同時引入Spring Cloud Ribbon和Spring Cloud Eureka依賴時恢恼,會觸發(fā)Eureka中實現(xiàn)的對Ribbon的自動化配置民傻。在與Spring Cloud Eureka結(jié)合使用時,配置將更加簡單,不在需要需要通過類似<clientName>.ribbon.<key>=<value>的參數(shù)指定具體的服務(wù)實例清單漓踢。而對于Ribbon的參數(shù)配置牵署,依然可使用2.2.2中的兩種配置方式,對于客戶端的配置方式可直接使用Eureka中的服務(wù)名作為<client>完成針對某個微服務(wù)的個性配置喧半。
Spring Cloud Ribbon默認實現(xiàn)了區(qū)域親和策略碟刺,可以通過Eureka實例的元數(shù)據(jù)配置來實現(xiàn)區(qū)域化的實例配置方案。
如:eureka.instance.metadataMap.zone=shanghai
在Spring Cloud Ribbon和Spring Cloud Eureka結(jié)合的工程中,可以通過參數(shù)配置的方式禁用Eureka對Ribbon服務(wù)實例的維護實現(xiàn)薯酝。
如:ribbon.eureka.enabled=false