點擊上方“程序員蝸牛g”,選擇“設為星標”

跟蝸牛哥一起,每天進步一點點

Feign第一次調用為什麼會很慢?_加載

程序員蝸牛g

大廠程序員一枚 跟蝸牛一起 每天進步一點點

33篇原創內容


公眾號

 

首先要了解Feign是如何進行遠程調用的,這裏麪包括,註冊中心、負載均衡、FeignClient之間的關係,微服務通過不論是eureka、nacos也好註冊到服務端,Feign是靠Ribbon做負載的,而Ribbon需要拿到註冊中心的服務列表,將服務進行負載緩存到本地,然後FeignClient客户端在進行調用,大概就是這麼一個過程。

Ribbon是如何進行負載的

首先我們要清楚Ribbon是如何進行負載的,也就是如何獲取nacos、eureka的服務列表,這個很關鍵。

Feign第一次調用為什麼會很慢?_加載_02


RibbonClientConfiguration

RibbonClientConfiguration類中通過LoadBalancer,我們知道ribbon是靠LoadBalancer做負載的

無非就是ILoadBalancer接口的方法,依次是添加新的服務、在負載均衡裏選擇一個服務、markServerDown服務下線、獲取服務列表、獲取存活的服務器、獲取所有服務器(包括健康和不健康的)

Feign第一次調用為什麼會很慢?_服務列表_03


ZoneAwareLoadBalancer

loadBalancer默認的是ZoneAwareLoadBalancer負載均衡器,通過繼承父類DynamicServerListLoadBalancerrestOfInit方法,裏面比較重要的兩個方法,enableAndInitLearnNewServersFeatureupdateListOfServers方法

Feign第一次調用為什麼會很慢?_加載_04

enableAndInitLearnNewServersFeature方法裏面

LOGGER.info("Using serverListUpdater {}", serverListUpdater.getClass().getSimpleName());
serverListUpdater.start(updateAction);

讓我們看ServerListUpdater.start方法的實現,通過自定義線程去拿,這就是獲取服務列表;

Feign第一次調用為什麼會很慢?_服務列表_05


Ribbon負載均衡策略

服務列表獲取説了,當然負載均衡的策略這塊也有必要講一下,主要有七種;

  • RoundRobinRule(輪詢策略,按照服務順序依次循環調用)
  • WeightedResponseTimeRule(權重比策略,優先選擇權重比高的服務,也就是服務響應時間比較短的,響應時間越長權重比越低)
  • RandomRule(隨機策略,服務提供者列表隨機選擇一個服務)
  • BestAvailableRule(最小連接數策略,獲取服務列表中連接數最小的服務實例)
  • RetryRule(重試策略,重試獲取已經失效的服務,指定時間沒有獲取到返回NULL)
  • AvailabilityFilteringRule(可用性敏感策略,過濾非健康服務實例,選擇lianji)
  • ZoneAvoidanceRule(區域敏感策略)

Ribbon-eager-load(飢餓加載)模式

Ribbon對於負載Client是在服務啓動後,發生調用的時候才會去創建Client,所以在第一次發生http請求調用的時候,不光要算上http的請求時間,還要算上Client的創建時間,所以第一次調用的時候才會很慢,寫個方法調用下;

System 服務調用System2服務

@GetMapping("/requestSystem2Api")
public String requestSystem2Api(){
    long startTime = System.currentTimeMillis();
    R<String> stringR = iTestServiceClient.testRequestMethod();
    if (null !=stringR){
        log.info("接口返回:"+stringR.getMsg());
    }
    long needTime = System.currentTimeMillis() - startTime;
    log.info("接口調用需要的時間:"+needTime);
    return "";
}

從調用日誌可以看出,第一次調用System2服務,Ribbon的DynamicServerListLoadBalancer會將feign客户端進行負載,然後進行調用,第一次調用的時間就是會長一些,第二次調用直接進行請求可以看到調用時間很快。

Feign第一次調用為什麼會很慢?_加載_06

開啓Ribbon飢餓加載

ribbon:
  nacos:
    enabled:true# 開啓naocos輪詢
eager-load:
   enabled:true# 開啓Ribbon的飢餓加載模式(防止第一次請求超時的問題)
   clients:Lxlxxx-system2# 指定需要開啓的服務(需要開啓Ribbon的飢餓加載模式)
   ReadTimeout:10000
   ConnectTimeout:10000
   MaxAutoRetries:0
   MaxAutoRetriesNextServer:1
   OkToRetryOnAllOperations:false

在項目啓動的時候,可以從日誌看到,已經把Lxlxxx-system2服務進行加載,從而避免了第一次請求超時的情況;

Feign第一次調用為什麼會很慢?_加載_07

總結

其實這種飢餓加載模式,類似於“客户端負載預熱”的一個操作,項目啓動的時候進行加載,防止服務之間調用可以因為數據量、業務邏輯處理複雜性導致接口超時,如果你的服務之間調用業務處理比較複雜、且慢,不妨可以試試這種解決方式。

如果這篇文章對您有所幫助,或者有所啓發的話,求一鍵三連:點贊、轉發、在看。

關注公眾號:woniuxgg,在公眾號中回覆:筆記  就可以獲得蝸牛為你精心準備的java實戰語雀筆記,回覆面試、開發手冊、有超讚的粉絲福利