springcloud netflix ribbon源碼解析
首先會介紹ribbon 相關(guān)的配置和實例的初始化過程,然后講解ribbon 是如何與openfeign 集成的,接著講解負載均衡器loadbalancercli ent , 最后依次講解iloadb alancer的實現(xiàn)和負載均衡策略rule 的實現(xiàn)。
配置和實例初始化
@ribbonclient 注解可以聲明ribbon 客戶端,設(shè)置ribbon 客戶端的名稱和配置類,configuration 屬性可以指定@configuration 的配置類,進行ribbon 相關(guān)的配置。@ribbonclient還會導入( import ) ribbonclientconfigurationregistrar 類來動態(tài)注冊ribbon 相關(guān)的beandefinition。
ribbonclientconfigurationregistrar 是importbeandefinitionregistrar 的實現(xiàn)類,importbeandefinitionregistrar 是spring 動態(tài)注冊beandefinition 的接口, 可以用來注冊ribbon 所需的beand的iition , 比如說ribbon客戶端實例( ribbon client ) lmportbeandefinitionregistrar的registerbeandefinitions 方法可以注冊ribbon 客戶端的配置類, 也就是@ribbonclient 的configuration 屬性值
與openfeign 的集成
feigncjientfactorybean 是創(chuàng)造feignclient 的工廠
類,在其getobject 方法中有一個分支判斷,當請求url 不為空時, 就會生成一個具有負載均衡的feignclient 。在這個過程中, openfeign 就默認引入了ribbon 的負載均衡實現(xiàn).
loadbalancerfeignclient#execute 方法會將普通的request 對象轉(zhuǎn)化為ribbonrequest , 并使用feignloadbalancer 實例來發(fā)送ribbonrequest。execute 方法會首先將request 的url轉(zhuǎn)化為對應的服務名稱,然后構(gòu)造出ribbonrequest 對象,接著調(diào)用lbclient 方法來生成feignloadbalancer 實例,最后調(diào)用feignloadbalancer 實例的executewithloadbalancer 方法來處理網(wǎng)絡(luò)請求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//loadbalancerfeignclient java public response execute(reqest reqi且est, request .options options) throws 工oexception { try { // :負載均衡時, host 就是需要調(diào)用的服務的名稱 uri asurn= uri . create(request.url()) ; string clientname = asur. gethost(); uri ur 工withouthost = cleanurl(reqi且est . url(), cl 工entname) ; //構(gòu)造ribbonrequest,delegate 一般就是真正發(fā)送網(wǎng)絡(luò)請求的客戶端,比如說okhttpclient 和apacheclient fe 工gnloadbalancer . r 工bbonrequest ribbonrequest = new feignloadbalancer . ribbonrequest( this . delegate , re 守uest , ur 工withouthost) ; iclientconfig requestconfig = getclientconfig(options, clientname) ; //executewithloadbalancer是進行負載均衡的關(guān)鍵 return lbclient(clientname) . executewithloadbalancer(ribbonrequest , requestconfig) . toresponse () ; catch (clientexception e) { ioexception io = findioexception(e) ; if ( io ! = null ) { throw io; throw new runtimeexception(e) ; private feignloadbalancer lbcl 工ent(str 工ng cl 工entname) { //調(diào)用cachingspringloadbalancerfactory 類的create方法。 return this . lbclientfactory . create(clientname) ; |
lbclientfactory 的參數(shù)是cachingspringloadbalancerfactory 的實例, 它是帶有緩存機制的feignloadbalancer 的工廠類。
create 方法的clientname 參數(shù)是指http 請求對應的服務端名稱, 它會首先使用這個名稱去緩存中查找是否已經(jīng)存在對應的實例。如果沒有, 再根據(jù)系統(tǒng)是否支持請求重試來創(chuàng)建出不同的f eignloadbalancer 實例, 最后將該實例存儲到緩存中.
feignloadbalancer 是openfeign 在不需要重試機制的情況下默認的負載均衡實現(xiàn)。它的execute 方法的實現(xiàn)很簡單,使用ribbonrequest 對象的客戶端來發(fā)送網(wǎng)絡(luò)請求,然后
將response 包裝成ribbonresponse 進行返回。ribbonrequest 的request 方法返回的對象就是構(gòu)造ribbonrequest 對象時傳入的delegate 參數(shù)。該參數(shù)是client 接口的實例, client接口是openfeign 真正發(fā)送網(wǎng)絡(luò)請求的客戶端, 比如說okhttpclient 和apacheclient 。feignloadbalancer 的execute 方法如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//fe i gnloadbalancer. ] ava public ribbonresponse execute(ribbonrequest request , iclientconfig configoverride) throws ioexception { request.options options ; if (configoverride ! = null ) { ribbonpropert 工es override = ribbonpropertes . from(configoverride); options = new request.options( else { override . connecttimeout(th 工s . connect timeout), override . readtimeout( this . readt 工meout)); options = new request . options(th 工s.connecttimeout, this readtimeout); response response = request . client() . execute(request . toreqest(), options) ; return new ribbonresponse(request . geturi() , response) ; |
feignloadbalancer 是abstractloadbalancerawarec!ient 的子類,其executewithloadbalance方法會首先創(chuàng)建一個loadbalancercommand 實例,然后在該實例的submit 方法的回調(diào)中調(diào)用子類的execute方法
其中, buildloadb a lan cercommand 方法使用了loadbalancercommand.builder 來創(chuàng)建loadbalancercornmand 實例,并將abstractloadbalancerawarec!ient 作loadbalancercontext接口的實例設(shè)置給loadbalancercommand 實例
loadbalancercontext 的getserverfromloadbalancer 方法調(diào)用了iloadbalancer 的chooseserver方法,從而完成了負載均衡中服務器的選擇。
負載均衡器loadbalancerclient
loadbalancerclient是ribbon 項目的核心類之一,可以在resttemplate 發(fā)送網(wǎng)絡(luò)請求時替代resttemplate 進行網(wǎng)絡(luò)調(diào)用
loadbalancerclient 接口繼承了servicelnstancechooser 接口,其choose 方法可以從服務器列表中依據(jù)負載均衡策略選出一個服務器實例
ribbonloadbalancerclient 是loadbalancerclient 的實現(xiàn)類之一, 它的execute 方法會首先使用iloadba lancer 來選擇服務器實例( server ),然后將該服務器實例封裝成ribbonserver 對象, 最后再調(diào)用loadbalancerrequest 的apply 方法進行網(wǎng)絡(luò)請求的處理。
iloadbalancer
iloadbalancer 是ribbon 的關(guān)鍵類之二, 它是定義負載均衡操作過程的接口。ribbon通過springclientfactory 工廠類的getloadbalancer 方法可以獲取iloadbalancer 實例。根據(jù)ribbon 的組件實例化機制, iloadbalnacer 實例是在ribbonautoconfiguration 中被創(chuàng)建生成的。
springclientfactory 中的實例都是ribbonclientconfiguration 或者自定義c onfiguration配置類創(chuàng)建的bean 實例。ribbonclientconfiguration 還創(chuàng)建了rule 、iping 和s e rver list
等相關(guān)組件的實例。使用者可以通過自定義配置類給出上述幾個組件的不同實例。
負載均衡策略實現(xiàn)
lrule 是定義ribbon 負載均衡策略的接口,你可以通過實現(xiàn)該接口來自定義自己的負載均衡策略, ribbon clientconfiguration 配置類則會給出!rule 的默認實例,rule 接口的choose 方法就是從一堆服務器中根據(jù)一定規(guī)則選出一個服務器。rule 有很多默認的實現(xiàn)類,這些實現(xiàn)類根據(jù)不同的算法和邏輯來進行負載均衡。
在大多數(shù)情況下, 這些默認的實現(xiàn)類是可以滿足需求的,如果有特殊需求,可以自己實現(xiàn)。ribbon 內(nèi)置的rule 子類如下所示。
- bestavailablerule :選擇最小請求數(shù)的服務器。
- clientconfigenabledroundrobinrule :使用randomrobinrule 隨機選擇一個服務器。
- roundrobinrul e :以randonrobin 方法輪詢選擇服務器。
- retryrule : 在選定的負載均衡策略上添加重試機制。
- weightedresponsetimerule :根據(jù)響應時間去計算一個權(quán)重( we ight ) ,響應時間越
- 長,權(quán)重越低,權(quán)重越低的服務器,被選擇的可能性就越低。
- zoneavoidancerule :根據(jù)服務器所屬的服務區(qū)的整體運行狀況來輪詢選擇。
到此這篇關(guān)于springcloud netflix ribbon源碼解析(推薦)的文章就介紹到這了,更多相關(guān)springcloud netflix ribbon源碼內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/weixin_44302240/article/details/112213459