<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          feign-eureka-ribbon的協(xié)作原理

          共 5226字,需瀏覽 11分鐘

           ·

          2023-07-16 05:20

          feign-eureka-ribbon的協(xié)作原理

          在我們的項(xiàng)目中使用了feigneurekaribbon這三個(gè)組件,最近想要在負(fù)載均衡上做些文章,需要了解這三個(gè)組件底層是如何協(xié)作的,這樣才能找到突破口,所以給這三個(gè)組件的源碼大概翻了一遍,最終整理出該筆記,希望對(duì)同樣對(duì)這三個(gè)組件是如何協(xié)作感興趣的讀者一些幫助;

          文中使用的spring cloud版本為Greenwich.SR6

          PS: 本文為純?cè)创a分析,所以配合源碼閱讀本文最佳;

          feign

          當(dāng)我們引入spring-cloud-openfeign-core的時(shí)候,會(huì)引入org.springframework.cloud.openfeign.ribbon.DefaultFeignLoadBalancedConfiguration這個(gè)配置文件,這個(gè)配置文件提供了一個(gè)feign.Client接口的實(shí)現(xiàn)org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClientfeign.Client接口是feign中最核心的接口,feign框架的所有網(wǎng)絡(luò)請(qǐng)求最終都會(huì)統(tǒng)一調(diào)用feign.Client,具體網(wǎng)絡(luò)請(qǐng)求如何發(fā)起feign本身并不關(guān)心,我們可以自己實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求,當(dāng)然,feign中也給我們默認(rèn)實(shí)現(xiàn)了一些,比如feign.Client.Defaultfeign.httpclient.ApacheHttpClient等,底層使用了不同的網(wǎng)絡(luò)框架來(lái)處理網(wǎng)絡(luò)請(qǐng)求,默認(rèn)的實(shí)現(xiàn)是feign.Client.Default,這個(gè)實(shí)現(xiàn)中使用了jdk自帶的java.net.HttpURLConnection實(shí)現(xiàn)了網(wǎng)絡(luò)請(qǐng)求,沒(méi)有連接池等概念,每次請(qǐng)求都會(huì)新建連接,效率比較低,不過(guò)這不在我們討論的重點(diǎn);

          本文不重點(diǎn)討論feign的網(wǎng)絡(luò)實(shí)現(xiàn),不過(guò)如果項(xiàng)目中有使用feign的話,要關(guān)注這點(diǎn),一定要替代默認(rèn)實(shí)現(xiàn),默認(rèn)實(shí)現(xiàn)的性能較差;

          ribbon

          雖然feign默認(rèn)的實(shí)現(xiàn)是feign.Client.Default,但是實(shí)際上feign框架并沒(méi)有直接使用該實(shí)現(xiàn),而是使用了org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient包裝了一層,我們的請(qǐng)求會(huì)被LoadBalancerFeignClient委托到com.netflix.client.AbstractLoadBalancerAwareClient#executeWithLoadBalancer(S, com.netflix.client.config.IClientConfig)方法處,該方法將請(qǐng)求提交到了com.netflix.loadbalancer.reactive.LoadBalancerCommand中,最終目的就是使用ribbon的負(fù)載均衡能力決策出一個(gè)com.netflix.loadbalancer.Server,而該Server就是為我們本次請(qǐng)求提供服務(wù)的服務(wù)端,包含ip、端口號(hào)等;

          從這里也可以看出,默認(rèn)情況下feign和ribbon是強(qiáng)綁定的;

          下面我們來(lái)分析Server是如何決策出來(lái)的,首先是LoadBalancerCommand中提供了com.netflix.loadbalancer.reactive.LoadBalancerCommand#selectServer方法來(lái)選擇為當(dāng)前請(qǐng)求提供服務(wù)的ServerselectServer方法并沒(méi)有直接實(shí)現(xiàn)該邏輯,而是將其委托到了com.netflix.loadbalancer.LoadBalancerContext#getServerFromLoadBalancer處,該方法中又將Server的決策邏輯委托到了com.netflix.loadbalancer.ILoadBalancer#chooseServer

          com.netflix.loadbalancer.ILoadBalancer是何時(shí)注入的呢?我們回到org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient#execute處,在這里,調(diào)用了lbClient方法來(lái)構(gòu)建了feign負(fù)載均衡FeignLoadBalancer的實(shí)例,lbClient方法中將構(gòu)建委托給了org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory#create方法,最終在該方法中構(gòu)建了FeignLoadBalancer的實(shí)例,該方法中通過(guò)調(diào)用org.springframework.cloud.netflix.ribbon.SpringClientFactory#getLoadBalancer來(lái)構(gòu)建了com.netflix.loadbalancer.ILoadBalancer實(shí)例,getLoadBalancer方法中通過(guò)調(diào)用org.springframework.cloud.context.named.NamedContextFactory#getInstance(java.lang.String, java.lang.Class<T>)以獲取bean的方式獲取到了ILoadBalancer實(shí)例,并將其注入了FeignLoadBalancer實(shí)例中;

          實(shí)際上SpringClientFactory繼承自org.springframework.cloud.context.named.NamedContextFactory,是ribbon自定義的NamedContextFactory,這是spring cloud context組件提供的一個(gè)工廠類,用于創(chuàng)建和管理具有名稱的應(yīng)用程序上下文;

          上個(gè)問(wèn)題解決了,但是現(xiàn)在又有了新問(wèn)題,org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory中的org.springframework.cloud.netflix.ribbon.SpringClientFactory實(shí)例又是在哪兒構(gòu)建的呢?ILoadBalancer類型的bean又是在哪兒聲明的呢?

          要回答這個(gè)問(wèn)題,就要引入ribbon組件了,當(dāng)我們引入spring-cloud-netflix-ribbon的時(shí)候,org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration就會(huì)被自動(dòng)引入,該配置中聲明了SpringClientFactory這個(gè)bean,同時(shí)該配置上添加了@RibbonClients注解,該注解引入了org.springframework.cloud.netflix.ribbon.RibbonClientConfigurationRegistrar,這個(gè)bean最終會(huì)掃描org.springframework.cloud.netflix.ribbon.RibbonClients注解和org.springframework.cloud.netflix.ribbon.RibbonClient注解來(lái)生成注冊(cè)一批org.springframework.cloud.netflix.ribbon.RibbonClientSpecificationbean定義,最終這些RibbonClientSpecification會(huì)被注入到我們構(gòu)建的SpringClientFactory中作為配置,而SpringClientFactory的默認(rèn)配置則是org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration,該配置中聲明了許多bean,其中就包含ILoadBalancer這個(gè)bean;

          eureka

          上邊提到了feignribbon是如何協(xié)作的,那feignribbon又是如何與eureka協(xié)作的呢?核心就在于ribbon提供的默認(rèn)ILoadBalancer的實(shí)現(xiàn)com.netflix.loadbalancer.ZoneAwareLoadBalancer,在ZoneAwareLoadBalancerchooseServer實(shí)現(xiàn)中,實(shí)際上并沒(méi)有實(shí)現(xiàn)具體的邏輯,具體的邏輯是委托給了com.netflix.loadbalancer.IRule#choose,而IRule這個(gè)bean在RibbonClientConfiguration配置類中也有,提供了一個(gè)默認(rèn)實(shí)現(xiàn)com.netflix.loadbalancer.ZoneAvoidanceRule,不過(guò)ZoneAvoidanceRulechoose方法中又先通過(guò)ILoadBalancergetAllServers獲取了所有Server列表,然后根據(jù)相關(guān)算法從里邊挑處了一個(gè)Server,不過(guò)我們對(duì)這些算法不關(guān)心,我們關(guān)心的是它如何對(duì)接上了eureka的服務(wù)發(fā)現(xiàn)的能力;

          現(xiàn)在我們繼續(xù)回到ILoadBalancer中,ribbon提供的默認(rèn)ILoadBalancer實(shí)現(xiàn)ZoneAwareLoadBalancer中通過(guò)com.netflix.loadbalancer.ServerList來(lái)獲取了所有Server列表,而ribboneureka協(xié)作的重點(diǎn)就在于ServerList上;

          當(dāng)我們引入spring-cloud-netflix-eureka-client的時(shí)候,org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration會(huì)被自動(dòng)引入,同樣的,該配置類上添加了@RibbonClients注解,與RibbonAutoConfiguration不同的是,該注解還指定了使用org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration配置類 ,而不是使用默認(rèn)的配置類,這個(gè)配置類中聲明了一個(gè)很重要的bean,那就是com.netflix.loadbalancer.ServerList這個(gè)bean,這個(gè)bean替代了ribbon默認(rèn)的ServerList實(shí)現(xiàn),其中使用了EurekaClient來(lái)獲取指定服務(wù)的所有服務(wù)提供方ip、端口等信息,這樣,ribbon就能使用到eureka提供的服務(wù)發(fā)現(xiàn)的能力了;

          總結(jié)

          看到上邊繞來(lái)繞去,是不是感覺(jué)腦瓜嗡嗡叫?




          1af855d667a210c8e312fbde42a268c5.webp




          簡(jiǎn)單總結(jié)下,feignribbon通過(guò)org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient關(guān)聯(lián)了起來(lái),ribbonfeign提供了負(fù)載均衡的能力,而eureka則通過(guò)org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList實(shí)現(xiàn)了ribboncom.netflix.loadbalancer.ServerList接口,來(lái)為ribbon提供服務(wù)發(fā)現(xiàn)能力;

          至此,feignribboneureka的協(xié)作原理我們已經(jīng)解析完畢,其中還有很多細(xì)節(jié)沒(méi)有講到,讀者可以自行閱讀源碼來(lái)細(xì)細(xì)品味,例如ribbon的負(fù)載均衡策略實(shí)現(xiàn)算法、ribbon是如何對(duì)服務(wù)發(fā)現(xiàn)給到的后端服務(wù)進(jìn)行健康檢查的、feign網(wǎng)絡(luò)請(qǐng)求的幾種內(nèi)置實(shí)現(xiàn)、eureka的分區(qū)負(fù)載均衡、NamedContextFactoryribbon中是如何使用的等等;

          聯(lián)系我
          • 作者微信:JoeKerouac
          • 微信公眾號(hào)(文章會(huì)第一時(shí)間更新到公眾號(hào),如果搜不出來(lái)可能是改名字了,加微信即可=_=|):代碼深度研究院
          • GitHub:https://github.com/JoeKerouac


          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色老板免费精品无码免费视频 | 在线视频日韩欧美 | 亚洲图片第一页 | 日韩性爱人人操 | 天天草天天干天天射 |