SpringCloud Netflix Ribbon源碼解析(推薦)
SpringCloud Netflix Ribbon源碼解析
首先會(huì)介紹Ribbon 相關(guān)的配置和實(shí)例的初始化過(guò)程,然后講解Ribbon 是如何與OpenFeign 集成的,接著講解負(fù)載均衡器LoadBalancerCli ent , 最后依次講解ILoadB alancer的實(shí)現(xiàn)和負(fù)載均衡策略Rule 的實(shí)現(xiàn)。
配置和實(shí)例初始化
@RibbonClient 注解可以聲明Ribbon 客戶端,設(shè)置Ribbon 客戶端的名稱和配置類,configuration 屬性可以指定@Configuration 的配置類,進(jìn)行Ribbon 相關(guān)的配置。@RibbonClient還會(huì)導(dǎo)入( import ) RibbonClientConfigurationRegistrar 類來(lái)動(dòng)態(tài)注冊(cè)Ribbon 相關(guān)的BeanDefinition。
RibbonClientConfigurationRegistrar 是ImportBeanDefinitionRegistrar 的實(shí)現(xiàn)類,ImportBeanDefinitionRegistrar 是Spring 動(dòng)態(tài)注冊(cè)BeanDefinition 的接口, 可以用來(lái)注冊(cè)Ribbon 所需的BeanD的iition , 比如說(shuō)Ribbon客戶端實(shí)例( Ribbon Client ) lmportBeanDefinitionRegistrar的registerBeanDefinitions 方法可以注冊(cè)Ribbon 客戶端的配置類, 也就是@RibbonClient 的configuration 屬性值
與OpenFeign 的集成
FeignCJientFactoryBean 是創(chuàng)造FeignClient 的工廠
類,在其getObject 方法中有一個(gè)分支判斷,當(dāng)請(qǐng)求URL 不為空時(shí), 就會(huì)生成一個(gè)具有負(fù)載均衡的FeignClient 。在這個(gè)過(guò)程中, OpenFeign 就默認(rèn)引入了Ribbon 的負(fù)載均衡實(shí)現(xiàn).
LoadBalancerFeignClient#execute 方法會(huì)將普通的Request 對(duì)象轉(zhuǎn)化為RibbonRequest , 并使用FeignLoadBalancer 實(shí)例來(lái)發(fā)送RibbonRequest。execute 方法會(huì)首先將Request 的URL轉(zhuǎn)化為對(duì)應(yīng)的服務(wù)名稱,然后構(gòu)造出RibbonRequest 對(duì)象,接著調(diào)用lbClient 方法來(lái)生成FeignLoadBalancer 實(shí)例,最后調(diào)用FeignLoadBalancer 實(shí)例的executeWithLoadBalancer 方法來(lái)處理網(wǎng)絡(luò)請(qǐng)求。
//LoadBalancerFeignClient java public Response execute(Reqest reqi且est, Request .Options options) throws 工OException { try { // :負(fù)載均衡時(shí), host 就是需要調(diào)用的服務(wù)的名稱 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ò)請(qǐng)求的客戶端,比如說(shuō)OkHttpClient 和ApacheClient Fe 工gnLoadBalancer . R 工bbonRequest ribbonRequest = new FeignLoadBalancer . RibbonRequest( this . delegate , re 守uest , ur 工WithoutHost) ; IClientConfig requestConfig = getClientConfig(options, clientName) ; //executeWithLoadBalancer是進(jìn)行負(fù)載均衡的關(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 的實(shí)例, 它是帶有緩存機(jī)制的FeignLoadBalancer 的工廠類。
create 方法的clientName 參數(shù)是指HTTP 請(qǐng)求對(duì)應(yīng)的服務(wù)端名稱, 它會(huì)首先使用這個(gè)名稱去緩存中查找是否已經(jīng)存在對(duì)應(yīng)的實(shí)例。如果沒(méi)有, 再根據(jù)系統(tǒng)是否支持請(qǐng)求重試來(lái)創(chuàng)建出不同的F eignLoadBalancer 實(shí)例, 最后將該實(shí)例存儲(chǔ)到緩存中.
FeignLoadBalancer 是OpenFeign 在不需要重試機(jī)制的情況下默認(rèn)的負(fù)載均衡實(shí)現(xiàn)。它的execute 方法的實(shí)現(xiàn)很簡(jiǎn)單,使用RibbonRequest 對(duì)象的客戶端來(lái)發(fā)送網(wǎng)絡(luò)請(qǐng)求,然后
將Response 包裝成RibbonResponse 進(jìn)行返回。RibbonRequest 的request 方法返回的對(duì)象就是構(gòu)造RibbonRequest 對(duì)象時(shí)傳入的delegate 參數(shù)。該參數(shù)是Client 接口的實(shí)例, Client接口是OpenFeign 真正發(fā)送網(wǎng)絡(luò)請(qǐng)求的客戶端, 比如說(shuō)OkHttpClient 和ApacheClient 。FeignLoadBalancer 的execute 方法如下所示:
//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方法會(huì)首先創(chuàng)建一個(gè)LoadBalancerCommand 實(shí)例,然后在該實(shí)例的submit 方法的回調(diào)中調(diào)用子類的execute方法
其中, buildLoadB a lan cerCommand 方法使用了LoadBalancerCommand.Builder 來(lái)創(chuàng)建LoadBalancerCornmand 實(shí)例,并將AbstractLoadBalancerAwareC!ient 作LoadBalancerContext接口的實(shí)例設(shè)置給LoadBalancerCommand 實(shí)例
LoadBalancerContext 的getServerFromLoadBalancer 方法調(diào)用了ILoadBalancer 的chooseServer方法,從而完成了負(fù)載均衡中服務(wù)器的選擇。
負(fù)載均衡器LoadBalancerClient
LoadBalancerClient是Ribbon 項(xiàng)目的核心類之一,可以在RestTemplate 發(fā)送網(wǎng)絡(luò)請(qǐng)求時(shí)替代RestTemplate 進(jìn)行網(wǎng)絡(luò)調(diào)用
LoadBalancerClient 接口繼承了ServicelnstanceChooser 接口,其choose 方法可以從服務(wù)器列表中依據(jù)負(fù)載均衡策略選出一個(gè)服務(wù)器實(shí)例
RibbonLoadBalancerClient 是LoadBalancerClient 的實(shí)現(xiàn)類之一, 它的execute 方法會(huì)首先使用ILoadBa lancer 來(lái)選擇服務(wù)器實(shí)例( Server ),然后將該服務(wù)器實(shí)例封裝成RibbonServer 對(duì)象, 最后再調(diào)用LoadBalancerRequest 的apply 方法進(jìn)行網(wǎng)絡(luò)請(qǐng)求的處理。
ILoadBalancer
ILoadBalancer 是Ribbon 的關(guān)鍵類之二, 它是定義負(fù)載均衡操作過(guò)程的接口。Ribbon通過(guò)SpringClientFactory 工廠類的getLoadBalancer 方法可以獲取ILoadBalancer 實(shí)例。根據(jù)Ribbon 的組件實(shí)例化機(jī)制, ILoadBalnacer 實(shí)例是在RibbonAutoConfiguration 中被創(chuàng)建生成的。
SpringClientFactory 中的實(shí)例都是RibbonClientConfiguration 或者自定義C onfiguration配置類創(chuàng)建的Bean 實(shí)例。RibbonClientConfiguration 還創(chuàng)建了Rule 、IPing 和S e rver List
等相關(guān)組件的實(shí)例。使用者可以通過(guò)自定義配置類給出上述幾個(gè)組件的不同實(shí)例。
負(fù)載均衡策略實(shí)現(xiàn)
lRule 是定義Ribbon 負(fù)載均衡策略的接口,你可以通過(guò)實(shí)現(xiàn)該接口來(lái)自定義自己的負(fù)載均衡策略, Ribbon ClientConfiguration 配置類則會(huì)給出!Rule 的默認(rèn)實(shí)例,Rule 接口的choose 方法就是從一堆服務(wù)器中根據(jù)一定規(guī)則選出一個(gè)服務(wù)器。Rule 有很多默認(rèn)的實(shí)現(xiàn)類,這些實(shí)現(xiàn)類根據(jù)不同的算法和邏輯來(lái)進(jìn)行負(fù)載均衡。
在大多數(shù)情況下, 這些默認(rèn)的實(shí)現(xiàn)類是可以滿足需求的,如果有特殊需求,可以自己實(shí)現(xiàn)。Ribbon 內(nèi)置的Rule 子類如下所示。
- BestAvailableRule :選擇最小請(qǐng)求數(shù)的服務(wù)器。
- ClientConfigEnabledRoundRobinRule :使用RandomRobinRule 隨機(jī)選擇一個(gè)服務(wù)器。
- RoundRobinRul e :以RandonRobin 方法輪詢選擇服務(wù)器。
- RetryRule : 在選定的負(fù)載均衡策略上添加重試機(jī)制。
- WeightedResponseTimeRule :根據(jù)響應(yīng)時(shí)間去計(jì)算一個(gè)權(quán)重( we ight ) ,響應(yīng)時(shí)間越
- 長(zhǎng),權(quán)重越低,權(quán)重越低的服務(wù)器,被選擇的可能性就越低。
- ZoneAvoidanceRule :根據(jù)服務(wù)器所屬的服務(wù)區(qū)的整體運(yùn)行狀況來(lái)輪詢選擇。
到此這篇關(guān)于SpringCloud Netflix Ribbon源碼解析(推薦)的文章就介紹到這了,更多相關(guān)SpringCloud Netflix Ribbon源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java經(jīng)理與員工的差異實(shí)現(xiàn)方法
這篇文章主要介紹了Java經(jīng)理與員工的差異實(shí)現(xiàn)方法,需要的朋友可以參考下2014-03-03Spring需要三個(gè)級(jí)別緩存解決循環(huán)依賴原理解析
這篇文章主要為大家介紹了Spring需要三個(gè)級(jí)別緩存解決循環(huán)依賴原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Java Web項(xiàng)目中Spring框架處理JSON格式數(shù)據(jù)的方法
Spring MVC是個(gè)靈活的框架,返回JSON數(shù)據(jù)的也有很多五花八門(mén)的方式,這里我們來(lái)整理一個(gè)最簡(jiǎn)單的Java Web項(xiàng)目中Spring框架處理JSON格式數(shù)據(jù)的方法:2016-05-05SpringBoot @value注解動(dòng)態(tài)刷新問(wèn)題小結(jié)
@Value注解 所對(duì)應(yīng)的數(shù)據(jù)源來(lái)自項(xiàng)目的 Environment 中,我們可以將數(shù)據(jù)庫(kù)或其他文件中的數(shù)據(jù),加載到項(xiàng)目的 Environment 中,然后 @Value注解 就可以動(dòng)態(tài)獲取到配置信息了,這篇文章主要介紹了SpringBoot @value注解動(dòng)態(tài)刷新,需要的朋友可以參考下2023-09-09Spring AOP中定義切點(diǎn)的實(shí)現(xiàn)方法示例
這篇文章主要介紹了Spring AOP中定義切點(diǎn)的實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了spring面向切面AOP定義切點(diǎn)的具體步驟、實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2020-01-01Java多線程案例實(shí)戰(zhàn)之定時(shí)器的實(shí)現(xiàn)
在Java中可以使用多線程和定時(shí)器來(lái)實(shí)現(xiàn)定時(shí)任務(wù),下面這篇文章主要給大家介紹了關(guān)于Java多線程案例之定時(shí)器實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01Java基礎(chǔ)強(qiáng)化訓(xùn)練輸入錯(cuò)誤即結(jié)束進(jìn)程
本文主要介紹了Java編程的基礎(chǔ)知識(shí)強(qiáng)化應(yīng)用,文中實(shí)例涉及到了許多基礎(chǔ)知識(shí),new對(duì)象,控制臺(tái)輸入,if語(yǔ)句等。很實(shí)用,需要的朋友可以參考下2017-09-09java實(shí)現(xiàn)簡(jiǎn)單的彈球游戲
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的彈球游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08