Ribbon負(fù)載均衡原理
作者:讓你變好的過程從來(lái)都不會(huì)很舒服
鏈接:https://www.jianshu.com/p/a1d6b5251b67
代碼參考:
Gitee:https://gitee.com/xn2001/cloudcode/tree/master/04-cloud-ribbon
GitHub:https://github.com/lexinhu/cloudcode/tree/master/04-cloud-ribbon
我們添加了 @LoadBalanced 注解,即可實(shí)現(xiàn)負(fù)載均衡功能,這是什么原理呢?
SpringCloud 底層提供了一個(gè)名為 Ribbon 的組件,來(lái)實(shí)現(xiàn)負(fù)載均衡功能。

源碼跟蹤
為什么我們只輸入了 service 名稱就可以訪問了呢?為什么不需要獲取ip和端口,這顯然有人幫我們根據(jù) service 名稱,獲取到了服務(wù)實(shí)例的ip和端口。它就是LoadBalancerInterceptor,這個(gè)類會(huì)在對(duì) RestTemplate 的請(qǐng)求進(jìn)行攔截,然后從 Eureka 根據(jù)服務(wù) id 獲取服務(wù)列表,隨后利用負(fù)載均衡算法得到真實(shí)的服務(wù)地址信息,替換服務(wù) id。
我們進(jìn)行源碼跟蹤:

這里的 intercept() 方法,攔截了用戶的 HttpRequest 請(qǐng)求,然后做了幾件事:
request.getURI():獲取請(qǐng)求uri,即 http://user-service/user/8originalUri.getHost():獲取uri路徑的主機(jī)名,其實(shí)就是服務(wù)iduser-servicethis.loadBalancer.execute():處理服務(wù)id,和用戶請(qǐng)求
這里的 this.loadBalancer 是 LoadBalancerClient 類型
繼續(xù)跟入 execute() 方法:

getLoadBalancer(serviceId):根據(jù)服務(wù)id獲取 ILoadBalancer,而 ILoadBalancer 會(huì)拿著服務(wù) id 去 eureka 中獲取服務(wù)列表。getServer(loadBalancer):利用內(nèi)置的負(fù)載均衡算法,從服務(wù)列表中選擇一個(gè)。在圖中可以看到獲取了8082端口的服務(wù)
可以看到獲取服務(wù)時(shí),通過一個(gè) getServer() 方法來(lái)做負(fù)載均衡:
繼續(xù)跟蹤源碼 chooseServer() 方法,發(fā)現(xiàn)這么一段代碼:

我們看看這個(gè)rule 是誰(shuí):

這里的 rule 默認(rèn)值是一個(gè) RoundRobinRule ,看類的介紹:

負(fù)載均衡默認(rèn)使用了輪訓(xùn)算法,當(dāng)然我們也可以自定義。
流程總結(jié)
SpringCloud Ribbon 底層采用了一個(gè)攔截器,攔截了 RestTemplate 發(fā)出的請(qǐng)求,對(duì)地址做了修改。
基本流程如下:
攔截我們的
RestTemplate請(qǐng)求 http://userservice/user/1RibbonLoadBalancerClient會(huì)從請(qǐng)求url中獲取服務(wù)名稱,也就是 user-serviceDynamicServerListLoadBalancer根據(jù) user-service 到 eureka 拉取服務(wù)列表eureka 返回列表,localhost:8081、localhost:8082
IRule利用內(nèi)置負(fù)載均衡規(guī)則,從列表中選擇一個(gè),例如 localhost:8081RibbonLoadBalancerClient修改請(qǐng)求地址,用 localhost:8081 替代 userservice,得到 http://localhost:8081/user/1,發(fā)起真實(shí)請(qǐng)求

負(fù)載均衡策略
負(fù)載均衡的規(guī)則都定義在 IRule 接口中,而 IRule 有很多不同的實(shí)現(xiàn)類:

不同規(guī)則的含義如下:
內(nèi)置負(fù)載均衡規(guī)則類 規(guī)則描述

默認(rèn)的實(shí)現(xiàn)就是 ZoneAvoidanceRule,是一種輪詢方案。
自定義策略
通過定義 IRule 實(shí)現(xiàn)可以修改負(fù)載均衡規(guī)則,有兩種方式:
1 代碼方式在 order-service 中的 OrderApplication 類中,定義一個(gè)新的 IRule(全局生效):

2 配置文件方式:在 order-service 的 application.yml 文件中,添加新的配置也可以修改規(guī)則(只對(duì)某個(gè)服務(wù)生效):
userservice: # 給需要調(diào)用的微服務(wù)配置負(fù)載均衡規(guī)則,orderservice服務(wù)去調(diào)用userservice服務(wù)
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 負(fù)載均衡規(guī)則
注意:一般用默認(rèn)的負(fù)載均衡規(guī)則,不做修改。
饑餓加載
當(dāng)我們啟動(dòng) orderservice,第一次訪問時(shí),時(shí)間消耗會(huì)大很多,這是因?yàn)?Ribbon 懶加載的機(jī)制。

Ribbon 默認(rèn)是采用懶加載,即第一次訪問時(shí)才會(huì)去創(chuàng)建 LoadBalanceClient,拉取集群地址,所以請(qǐng)求時(shí)間會(huì)很長(zhǎng)。
而饑餓加載則會(huì)在項(xiàng)目啟動(dòng)時(shí)創(chuàng)建 LoadBalanceClient,降低第一次訪問的耗時(shí),通過下面配置開啟饑餓加載:
ribbon:
eager-load:
enabled: true
clients: userservice # 項(xiàng)目啟動(dòng)時(shí)直接去拉取userservice的集群,多個(gè)用","隔開
推薦閱讀:
世界的真實(shí)格局分析,地球人類社會(huì)底層運(yùn)行原理
不是你需要中臺(tái),而是一名合格的架構(gòu)師(附各大廠中臺(tái)建設(shè)PPT)
企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案
論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?
企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!
【中臺(tái)實(shí)踐】華為大數(shù)據(jù)中臺(tái)架構(gòu)分享.pdf
華為如何實(shí)施數(shù)字化轉(zhuǎn)型(附PPT)
