作者 | 波哥
審校 | 重樓
在現(xiàn)代分布式微服務(wù)架構(gòu)中,負(fù)載均衡是保證系統(tǒng)高可用、高性能的關(guān)鍵組件之一。Netflix Ribbon作為Netflix開源的負(fù)載均衡庫,為微服務(wù)架構(gòu)提供了強(qiáng)大的負(fù)載均衡能力,極大地促進(jìn)了微服務(wù)間的通信和協(xié)作。本篇筆者將深入剖析Netflix Ribbon的底層實現(xiàn)原理,帶您揭開其神秘面紗。
Netflix Ribbon是Netflix開源的負(fù)載均衡庫,它可以無縫集成到微服務(wù)架構(gòu)中,提供了多種負(fù)載均衡策略和豐富的配置選項,幫助開發(fā)者實現(xiàn)高性能、高可用的服務(wù)調(diào)用。先來看下Ribbond 架構(gòu):
1.Ribbon的架構(gòu)
Ribbon的架構(gòu)主要由以下幾個核心組件構(gòu)成:
- IClientConfig:配置接口,用于獲取配置信息,如連接超時、讀取超時等。
- IRule:負(fù)載均衡規(guī)則接口,用于決定請求應(yīng)該轉(zhuǎn)發(fā)到哪個服務(wù)實例。
其中:
- choose(Object key): 從所有服務(wù)實例中選擇一個,根據(jù)具體的負(fù)載均衡規(guī)則,返回選定的服務(wù)實例。
- setLoadBalancer(ILoadBalancer lb): 設(shè)置與負(fù)載均衡規(guī)則相關(guān)的負(fù)載均衡器。
- getLoadBalancer(): 獲取與負(fù)載均衡規(guī)則相關(guān)聯(lián)的負(fù)載均衡器。
IRule 接口提供了選擇服務(wù)實例的方法,具體選擇哪個服務(wù)實例取決于實現(xiàn)該接口的負(fù)載均衡規(guī)則。這個規(guī)則可以是輪詢、隨機(jī)、加權(quán)輪詢等不同的策略。使用示例如下:
當(dāng)然我們一般使用是和Spring/SpringBoot整合使用,只需要在配置中加以配置即可。如果想實現(xiàn)自己的選擇機(jī)制,則只需要實現(xiàn)IRule,并完成使用配置即可。
- IPing:用于檢測服務(wù)實例的存活狀態(tài)。
主要有兩種實現(xiàn)方式:PingUrl 和 PingConstant。
PingUrl 實現(xiàn)通過向服務(wù)實例發(fā)送HTTP請求來檢查其健康狀態(tài)。默認(rèn)情況下,它會向服務(wù)實例的 / 路徑發(fā)送 GET 請求來檢查服務(wù)實例是否存活。
而PingConstant 實現(xiàn)則更簡單粗暴,無論什么情況下都返回 true,表示服務(wù)實例一直存活:
- ServerList:用于獲取所有可用的服務(wù)實例列表。
該接口有兩個方法:
- getInitialListOfServers(): 用于獲取初始化時所有可用的服務(wù)實例列表。
- getUpdatedListOfServers(): 用于獲取更新后的所有服務(wù)實例列表,包括動態(tài)刷新的列表。
ServerList 接口的實現(xiàn)是由具體的服務(wù)發(fā)現(xiàn)組件完成的。在 Netflix Ribbon 中,常用的服務(wù)發(fā)現(xiàn)組件是 Netflix Eureka,它可以通過 Eureka Server 獲取服務(wù)實例信息。
例如,Netflix Ribbon 提供了 DiscoveryEnabledNIWSServerList,它是通過 Eureka 獲取服務(wù)實例的一個實現(xiàn)類。這個實現(xiàn)類會調(diào)用 Eureka Client 獲取服務(wù)實例的信息,然后將服務(wù)實例封裝成 Ribbon 的 Server 對象。
- ServerListFilter:用于對服務(wù)實例列表進(jìn)行過濾,以適應(yīng)特定需求。
它只有getFilteredListOfServers這個方法,用于過濾服務(wù)實例列表,返回過濾后的服務(wù)實例列表。
ServerListFilter允許我們自定義過濾規(guī)則,以決定負(fù)載均衡器最終選擇的服務(wù)實例。我們可以根據(jù)自己的需求實現(xiàn)這個接口,定義自己的過濾規(guī)則。這個過程可以包括排除一些不符合條件的服務(wù)實例,或者根據(jù)特定標(biāo)準(zhǔn)重新排序服務(wù)實例列表等。
在 Netflix Ribbon 中,有一些內(nèi)置的過濾器,例如 ZonePreferenceServerListFilter、ZoneAffinityServerListFilter 等。這些過濾器基于服務(wù)實例所在的區(qū)域(Zone)來進(jìn)行服務(wù)實例的過濾和排序,例如:
2.Ribbon的負(fù)載均衡流程
下面詳細(xì)介紹下Ribbon的負(fù)載均衡流程:
- 獲取服務(wù)實例列表:Ribbon通過ServerList獲取可用的服務(wù)實例列表。
- 過濾服務(wù)實例:Ribbon會通過ServerListFilter對服務(wù)實例列表進(jìn)行過濾,可能會過濾掉一些不符合特定條件的實例。
- 選擇負(fù)載均衡策略:根據(jù)IRule選擇合適的負(fù)載均衡策略,如輪詢、隨機(jī)、加權(quán)輪詢等。這里的IRule可以是我們自己實現(xiàn)的規(guī)則。
- 選擇目標(biāo)服務(wù)實例:根據(jù)負(fù)載均衡策略,選擇一個目標(biāo)服務(wù)實例。
- 執(zhí)行請求:將請求發(fā)送到選擇的服務(wù)實例上。
3. Ribbon具體使用
接下來,我們詳細(xì)說明下如何在項目中使用Ribbon。
- 首先,我們需要在Spring配置文件中初始化Ribbon(當(dāng)然maven的配置,各位老鐵就自己去配置了):
在上述配置中,我們通過ribbonRule指定了負(fù)載均衡規(guī)則,這里使用了AvailabilityFilteringRule,它會根據(jù)服務(wù)實例的狀態(tài)來判斷是否選擇該實例。而ribbonPing則用于設(shè)置服務(wù)實例的健康檢查策略。
- 發(fā)起服務(wù)調(diào)用
接下來,我們通過RestTemplate來發(fā)起服務(wù)調(diào)用:
在這段代碼中,我們通過RestTemplate發(fā)起了對名為SERVICE-PROVIDER的服務(wù)的調(diào)用。
- 實現(xiàn)負(fù)載均衡
通過上述配置和代碼,Ribbon將會根據(jù)我們指定的負(fù)載均衡規(guī)則和健康檢查策略來選擇合適的服務(wù)實例,從而實現(xiàn)負(fù)載均衡。
本篇對Netflix Ribbon的底層實現(xiàn)原理進(jìn)行了簡要介紹,涵蓋了其核心組件、架構(gòu)、負(fù)載均衡流程以及實現(xiàn)原理的基本概念。深入理解Netflix Ribbon對于構(gòu)建高性能、高可用的微服務(wù)架構(gòu)至關(guān)重要,希望能對您有所幫助。
作者介紹
波哥,互聯(lián)行業(yè)從業(yè)10余年,先后擔(dān)任項目總監(jiān)及架構(gòu)師。目前專攻技術(shù),喜歡研究技術(shù)原理。技術(shù)全面,主攻Java,精通JVM底層機(jī)制及Spring全家桶底層框架原理,熟練掌握當(dāng)前主流的中間件、服務(wù)網(wǎng)格等技術(shù)原理。