Netflix:['netfliːks]
ribbon:英[ˈrɪbən]美[ˈrɪbən]
n. 帶; 绶帶; (列印機的) 色帶; 帶狀物;
v. 把…撕成條帶; 用緞帶裝飾; 形成帶狀;
目前主流的LB方案可分成兩類:
一種是集中式LB, 即在服務的消費方和提供方之間使用獨立的LB設施(可以是硬體,如F5, 也可以是軟體,如nginx), 由該設施負責把通路請求通過某種政策轉發至服務的提供方;
另一種是程序内LB,将LB邏輯內建到消費方,消費方從服務注冊中心獲知有哪些位址可用,然後自己再從這些位址中選擇出一個合适的伺服器。Ribbon就屬于後者,它隻是一個類庫,內建于消費方程序,消費方通過它來擷取到服務提供方的位址。
軟負載均衡的實作方式有兩種,分别是服務端的負載均衡和用戶端的負載均衡
服務端負載均衡:當浏覽器向背景送出請求的時候,會首先向反向代理伺服器發送請求,反向代理伺服器會根據用戶端部署的ip:port映射表以及負載均衡政策,來決定向哪台伺服器發送請求,一般會使用到nginx反向代理技術。
用戶端負載均衡:當浏覽器向背景送出請求的時候,用戶端會向服務注冊器(例如:Eureka Server),拉取注冊到伺服器的可用服務資訊,然後根據負載均衡政策,直接命中哪台伺服器發送請求。這整個過程都是在用戶端完成的,并不需要反向代理伺服器的參與。
Ribbon是Netflix釋出的開源項目,主要功能是提供用戶端的軟體負載均衡算法,将Netflix的中間層服務連接配接在一起。Ribbon用戶端元件提供一系列完善的配置項如連接配接逾時,重試等。簡單的說,就是在配置檔案中列出Load Balancer後面所有的機器,Ribbon會自動的幫助你基于某種規則(如簡單輪詢,随即連接配接等)去連接配接這些機器。我們也很容易使用Ribbon實作自定義的負載均衡算法。

Ribbon的核心元件(均為接口類型)有以下幾個:
ServerList
用于擷取位址清單。它既可以是靜态的(提供一組固定的位址),也可以是動态的(從注冊中心中定期查詢位址清單)。
ServerListFilter
僅當使用動态ServerList時使用,用于在原始的服務清單中使用一定政策過慮掉一部分位址。
IRule
選擇一個最終的服務位址作為LB結果。選擇政策有輪詢、根據響應時間權重、斷路器(當Hystrix可用時)等。
Ribbon在工作時首選會通過ServerList來擷取所有可用的服務清單,然後通過ServerListFilter過慮掉一部分位址,最後在剩下的位址中通過IRule選擇出一台伺服器作為最終結果。
當與Eureka組合使用Ribbon時,<code>ServerList</code>接口會使用<code>DiscoveryEnabledNIWSServerList</code>實作,該實作會通過 EurekaClient 向Eureka伺服器擷取可用的服務清單。<code>ServerListFilter</code>預設實作為<code>ZonePreferenceServerListFilter</code>,其作用是過慮掉不同zone下的服務(即優先選擇同一個zone下的位址)。<code>IRule</code>使用<code>ZoneAvoidanceRule</code>實作,它是一種複合政策,同時使用<code>ZoneAvoidancePredicate</code>和<code>AvailabilityPredicate</code>來判斷是否選擇某個server,前者以一個區域為機關判斷可用性,對于不可用的區域整個丢棄,從剩下區域中選可用的server;後者用于過濾掉連接配接數過多和斷路器處于打開狀态的server。該複合政策經過上述兩次過慮後最終選擇出一個位址作為LB結果。
政策名
政策聲明
政策描述
實作說明
BestAvailableRule
public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule
選擇一個最小的并發請求的server
逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server
AvailabilityFilteringRule
public class AvailabilityFilteringRule extends PredicateBasedRule
過濾掉那些因為一直連接配接失敗的被标記為circuit tripped的後端server,并過濾掉那些高并發的的後端server(active connections 超過配置的門檻值)
使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status裡記錄的各個server的運作狀态
WeightedResponseTimeRule
public class WeightedResponseTimeRule extends RoundRobinRule
根據相應時間配置設定一個weight,相應時間越長,weight越小,被選中的可能性越低。
一個背景線程定期的從status裡面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始運作,沒有形成statas時,使用roubine政策選擇server。
RetryRule
public class RetryRule extends AbstractLoadBalancerRule
對標明的負載均衡政策機上重試機制。
在一個配置時間段内當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server
RoundRobinRule
public class RoundRobinRule extends AbstractLoadBalancerRule
簡單輪詢服務清單來選擇伺服器。它是Ribbon預設的負載均衡規則。
輪詢index,選擇index對應位置的server
RandomRule
public class RandomRule extends AbstractLoadBalancerRule
随機選擇一個server
在index上随機,選擇index對應位置的server
ZoneAvoidanceRule
public class ZoneAvoidanceRule extends PredicateBasedRule
複合判斷server所在區域的性能和server的可用性選擇server
使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的運作性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于過濾掉連接配接數過多的Server。
Ribbon架構圖
這裡以随機通路政策來舉個栗子:
1、ribbon配置檔案添加:随機通路政策
其中service-B是我注冊到Eureka的serviceID,一共起了3個示例。
2、main類注冊:
一定記得加第二個注冊,很多文章沒有。裡面配具體的政策。
3、Controller:
關于負載均衡相關的四個配置項
這些配置項的字首是【用戶端名稱】.ribbon
The supported properties are listed below and should be prefixed by <code><clientName>.ribbon.</code>:
<code>NFLoadBalancerClassName</code>: should implement <code>ILoadBalancer</code>
<code>NFLoadBalancerRuleClassName</code>: should implement <code>IRule</code>
<code>NFLoadBalancerPingClassName</code>: should implement <code>IPing</code>
<code>NIWSServerListClassName</code>: should implement <code>ServerList</code>
<code>NIWSServerListFilterClassName</code> should implement <code>ServerListFilter</code>
其中比較重要的是<code>NFLoadBalancerRuleClassName</code>,我們可以通過這個配置項定制需要的負載均衡規則,可以是ribbon提供的原生的幾種規則類,也可以是自己實作的規則類,這些類都實作了IRule接口。
<code>NFLoadBalancerPingClassName</code>用于配置檢視伺服器是否存活。
<code>NFLoadBalancerRuleClassName</code>指定負載均衡器的實作類。當然,可以設定自己實作的負載均衡器。
<code>NIWSServerListClassName</code>是伺服器清單的處理類,用來維護伺服器清單的。Ribbon已經實作了動态伺服器清單。
<code>NIWSServerListFilterClassName</code>是伺服器的攔截類。
一種直接調用ConfigurationManager擷取配置執行個體,然後設定配置屬性;一種是在application.yml中配置。