當前位置: 妍妍網 > 碼農

面試官:Feign 第一次呼叫為什麽會很慢?

2024-02-27碼農

作者:Lxlxxx
連結:https://juejin.cn/post/7249624466150408250 前言

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

# Ribbon是如何進行負載的

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


# RibbonClientConfiguration

RibbonClientConfiguration類中透過LoadBalancer,我們知道ribbon是靠LoadBalancer做負載的 無非就是ILoadBalancer介面的方法,依次是添加新的服務、在負載均衡裏選擇一個服務、markServerDown服務下線、獲取服務列表、獲取存活的伺服器、獲取所有伺服器(包括健康和不健康的)

# ZoneAwareLoadBalancer

loadBalancer預設的是ZoneAwareLoadBalancer負載均衡器,透過繼承父類DynamicServerListLoadBalancer的restOfInit方法,裏面比較重要的兩個方法,enableAndInitLearnNewServersFeature和updateListOfServers方法

enableAndInitLearnNewServersFeature方法裏面

LOGGER.info("UsingserverListUpdater {}", serverListUpdater.get class().getSimpleName());serverListUpdater.start(updateAction);

讓我們看ServerListUpdater.start方法的實作,透過自訂執行緒去拿,這就是獲取服務列表;


# 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客戶端進行負載,然後進行呼叫,第一次呼叫的時間就是會長一些,第二次呼叫直接進行請求可以看到呼叫時間很快。

    開啟Ribbon饑餓載入

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

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

    # 總結

    其實這種饑餓載入模式,類似於「客戶端負載預熱」的一個操作,計畫啟動的時候進行載入,防止服務之間呼叫可以因為數據量、業務邏輯處理復雜性導致介面超時,如果你的服務之間呼叫業務處理比較復雜、且慢,不妨可以試試這種解決方式。

    熱門推薦