前言
首先要了解 Feign 是如何進(jìn)行遠(yuǎn)程調(diào)用的,這里面包括,注冊(cè)中心、負(fù)載均衡、FeignClient 之間的關(guān)系,微服務(wù)通過(guò)不論是 eureka、nacos 也好注冊(cè)到服務(wù)端,F(xiàn)eign 是靠 Ribbon 做負(fù)載的,而 Ribbon 需要拿到注冊(cè)中心的服務(wù)列表,將服務(wù)進(jìn)行負(fù)載緩存到本地,然后 FeignClient 客戶(hù)端在進(jìn)行調(diào)用,大概就是這么一個(gè)過(guò)程。
Ribbon是如何進(jìn)行負(fù)載的
首先我們要清楚 Ribbon 是如何進(jìn)行負(fù)載的,也就是如何獲取 nacos、eureka 的服務(wù)列表,這個(gè)很關(guān)鍵。
Ribbon是如何進(jìn)行負(fù)載的
RibbonClientConfiguration
RibbonClientConfiguration 類(lèi)中通過(guò) LoadBalancer,我們知道 ribbon 是靠LoadBalancer 做負(fù)載的 無(wú)非就是 ILoadBalancer 接口的方法,依次是添加新的服務(wù)、在負(fù)載均衡里選擇一個(gè)服務(wù)、markServerDown 服務(wù)下線(xiàn)、獲取服務(wù)列表、獲取存活的服務(wù)器、獲取所有服務(wù)器(包括健康和不健康的)
ILoadBalancer 接口
ZoneAwareLoadBalancer
loadBalancer 默認(rèn)的是 ZoneAwareLoadBalancer 負(fù)載均衡器,通過(guò)繼承父類(lèi)DynamicServerListLoadBalancer 的 restOfInit 方法,里面比較重要的兩個(gè)方法,enableAndInitLearnNewServersFeature和updateListOfServers 方法
restOfInit 方法
enableAndInitLearnNewServersFeature 方法里面。
LOGGER.info("UsingserverListUpdater{}",serverListUpdater.getClass().getSimpleName()); serverListUpdater.start(updateAction);
讓我們看 ServerListUpdater.start 方法的實(shí)現(xiàn),通過(guò)自定義線(xiàn)程去拿,這就是獲取服務(wù)列表。
ServerListUpdater.start
Ribbon負(fù)載均衡策略
服務(wù)列表獲取說(shuō)了,當(dāng)然負(fù)載均衡的策略這塊也有必要講一下,主要有七種;
RoundRobinRule(輪詢(xún)策略,按照服務(wù)順序依次循環(huán)調(diào)用)
WeightedResponseTimeRule(權(quán)重比策略,優(yōu)先選擇權(quán)重比高的服務(wù),也就是服務(wù)響應(yīng)時(shí)間比較短的,響應(yīng)時(shí)間越長(zhǎng)權(quán)重比越低)
RandomRule(隨機(jī)策略,服務(wù)提供者列表隨機(jī)選擇一個(gè)服務(wù))
BestAvailableRule(最小連接數(shù)策略,獲取服務(wù)列表中連接數(shù)最小的服務(wù)實(shí)例)
RetryRule(重試策略,重試獲取已經(jīng)失效的服務(wù),指定時(shí)間沒(méi)有獲取到返回NULL)
AvailabilityFilteringRule(可用性敏感策略,過(guò)濾非健康服務(wù)實(shí)例,選擇lianji)
ZoneAvoidanceRule(區(qū)域敏感策略)
Ribbon-eager-load(饑餓加載)模式
Ribbon 對(duì)于負(fù)載 Client 是在服務(wù)啟動(dòng)后,發(fā)生調(diào)用的時(shí)候才會(huì)去創(chuàng)建 Client,所以在第一次發(fā)生 http 請(qǐng)求調(diào)用的時(shí)候,不光要算上 http 的請(qǐng)求時(shí)間,還要算上 Client 的創(chuàng)建時(shí)間,所以第一次調(diào)用的時(shí)候才會(huì)很慢,寫(xiě)個(gè)方法調(diào)用下。
System 服務(wù)調(diào)用 System2 服務(wù)
@GetMapping("/requestSystem2Api") publicStringrequestSystem2Api(){ longstartTime=System.currentTimeMillis(); RstringR=iTestServiceClient.testRequestMethod(); if(null!=stringR){ log.info("接口返回:"+stringR.getMsg()); } longneedTime=System.currentTimeMillis()-startTime; log.info("接口調(diào)用需要的時(shí)間:"+needTime); return""; }
從調(diào)用日志可以看出,第一次調(diào)用 System2 服務(wù),Ribbon 的 DynamicServerListLoadBalancer 會(huì)將 feign 客戶(hù)端進(jìn)行負(fù)載,然后進(jìn)行調(diào)用,第一次調(diào)用的時(shí)間就是會(huì)長(zhǎng)一些,第二次調(diào)用直接進(jìn)行請(qǐng)求可以看到調(diào)用時(shí)間很快。
第一次慢,第二次快
開(kāi)啟Ribbon饑餓加載
ribbon: nacos: enabled:true#開(kāi)啟naocos輪詢(xún) eager-load: enabled:true#開(kāi)啟Ribbon的饑餓加載模式(防止第一次請(qǐng)求超時(shí)的問(wèn)題) clients:Lxlxxx-system2#指定需要開(kāi)啟的服務(wù)(需要開(kāi)啟Ribbon的饑餓加載模式) ReadTimeout:10000 ConnectTimeout:10000 MaxAutoRetries:0 MaxAutoRetriesNextServer:1 OkToRetryOnAllOperations:false
在項(xiàng)目啟動(dòng)的時(shí)候,可以從日志看到,已經(jīng)把 Lxlxxx-system2 服務(wù)進(jìn)行加載,從而避免了第一次請(qǐng)求超時(shí)的情況。
開(kāi)啟Ribbon饑餓加載
總結(jié)
其實(shí)這種饑餓加載模式,類(lèi)似于“客戶(hù)端負(fù)載預(yù)熱”的一個(gè)操作,項(xiàng)目啟動(dòng)的時(shí)候進(jìn)行加載,防止服務(wù)之間調(diào)用可以因?yàn)閿?shù)據(jù)量、業(yè)務(wù)邏輯處理復(fù)雜性導(dǎo)致接口超時(shí),如果你的服務(wù)之間調(diào)用業(yè)務(wù)處理比較復(fù)雜、且慢,不妨可以試試這種解決方式。
審核編輯:劉清
-
HTTP接口
+關(guān)注
關(guān)注
0文章
21瀏覽量
1768 -
負(fù)載均衡器
+關(guān)注
關(guān)注
0文章
18瀏覽量
2573
原文標(biāo)題:面試官:Feign 第一次調(diào)用為什么會(huì)很慢?大部分人都答不上來(lái)!
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論