負載均衡 —— SpringCloud Netflix Ribbon

来源:https://www.cnblogs.com/Yee-Q/archive/2023/09/23/17725179.html
-Advertisement-
Play Games

Ribbon 簡介 Ribbon 是 Netfix 客戶端的負載均衡器,可對 HTTP 和 TCP 客戶端的行為進行控制。為 Ribbon 配置服務提供者地址後,Ribbon 就可以基於某種負載均衡演算法自動幫助服務消費者去請求。Ribbon 預設提供了很多負載均衡演算法,例如輪詢、隨機等,也可以為 R ...


Ribbon 簡介

Ribbon 是 Netfix 客戶端的負載均衡器,可對 HTTP 和 TCP 客戶端的行為進行控制。為 Ribbon 配置服務提供者地址後,Ribbon 就可以基於某種負載均衡演算法自動幫助服務消費者去請求。Ribbon 預設提供了很多負載均衡演算法,例如輪詢、隨機等,也可以為 Ribbon 實現自定義的負載均衡演算法

Ribbon 有以下幾個重要概念:

  • Rule:該組件主要決定從候選伺服器中返回哪個伺服器地址進行遠程調用的操作
  • Ping:在後臺運行的組件,用來確認哪些伺服器是存活可用的
  • ServerList:當前可以用作 LB 的伺服器列表,該列表可以是靜態的,也可以是動態的。如果是動態列表(例如從 Eurka 伺服器獲取),就會有一個後臺線程按照時間間隔刷新列表

Ribbon 提供了以下幾種 Rule:

  • RoundRobinRule:最簡單的規則,會在 ServerList 中依次輪詢調用
  • RandomRule:隨機
  • AvailabilityFileringRule:在這種規則下 Ribbon 集成了 Hystrix 的功能,預設情況下調用某個遠程方法失敗三次後斷路器的開關會被打開,而之後的請求中 Ribbon 會跳過這個伺服器地址,直到三十秒之後斷路器關閉後才會重新加入調用列表
  • WeightedResponseTimeRule:將響應時間作為權重的負載規則,某個伺服器的響應時越長,它的權重就越低,具體選擇伺服器時,結合權重進行隨機選擇
  • RetryRule:按照 RoundRobinRule(輪詢)策略獲取服務,如果獲取服務失敗,就在指定時間內重試,獲取可用的服務
  • BestAvailableRule:先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最小的服務
  • ZoneAvoidanceRule:複合判斷 Server 所在區域的性能和 Server 的可用性選擇伺服器

負載均衡演算法

服務消費者從服務配置中心獲取服務的地址列表後需要選取其中一臺發起 RPC/HTTP 調用,這時需要用到具體的負載均衡演算法

1. 輪詢法

輪詢法是指將請求按順序輪流分配到後端伺服器上,均衡地對待後端的每一臺伺服器,不關心伺服器實際的連接數和當前系統負載

2. 加權輪詢法

簡單的輪詢法並不考慮後端機器的性能和負載差異,加權輪詢法可以很好地處理這一問題,它將按照順序且按照權重分派給後端伺服器,給性能高、負載低的機器配置較高的權重,讓其處理較多的請求,給性能低、負載高的機器配置較低的權重,讓其處理較少的請求

假設有 9 個客戶端請求、3 台後端伺服器,後端伺服器 1 被賦予權值 1,後端伺服器2被賦予值 2,後端伺服器 3 賦值 3,這樣一來,客戶端請求 1、2、3 都被分派到伺服器 3 處理,客戶端請求 4、5 被分派到伺服器 2 處,客戶端請求 6 被分派到伺服器 1 處理,客戶端請求 7、8、9 被分派到伺服器 3 處理,以此類推

3. 隨機法

隨機法也很簡單,就是隨機選擇一臺後端伺服器進行請求處理,由於每次伺服器被挑中的概率都一樣,因此客戶端的請求可以被均勻地分派到所有的後端伺服器上

4. 加權隨機法

加權隨機法跟加權輪詢法類似,根據後臺伺服器不同的配置和負載情況配置不同的權重,不同的是,它是按照權重來隨機選取伺服器的,而非順序

比如希望抽到 A 的概率是 50%、抽到 B 和 C 的概率是 20%、抽到 D 的概率是 10%,一般來說,我們可以給各項附加一個權重,抽取的概率正比於這個權重,上述集合就成了 {A:5,B:2,C:2,D:1),擴展這個集合,使每一項出現的次數與其權重正相關,即 {A,A,A,A,A,B,BC,C,D},然後就可以用均勻隨機演算法從中選取了

5. 源地址哈希法

源地址哈希是根據獲取客戶端的 IP 地址,通過哈希函數計算得到一個數值,用該數值對伺服器列表的大小進行取模運算,得到的結果便是客戶端要訪問伺服器的序號。採用源地址哈希法進行負載均衡,當後端伺服器列表不變時,同一個 IP 地址的客戶端,每次都會映射到同一臺後端伺服器進行訪問,但當後端伺服器增加或者減少時,由於次數用於取模的伺服器總數發生了變化,就導致同一哈希值的請求無法命中同一臺伺服器,節點數越高,命中率越低

6. 一致性哈希法

一致性哈希法解決了分散式環境下機器增加或者減少時簡單的取模運算無法獲取較高命中率的問題,通過一個一致性哈希環的數據結構實現映射,具體演算法過程為:先構造一個長度為 2 的 32 次方的整數環(一致性哈希環),根據節點計算得出的哈希值將緩存伺服器節點放置在這個哈希環上,然後在哈希環上順時針查找距離這個哈希值最近的伺服器節點,完成請求到伺服器的映射

假設現在增加一臺伺服器 4,那麼影響的就只有一個的請求,也就是說原本到伺服器 1 的請求會被映射到伺服器 4 上,雖然也會影響到整個集群,但是影響的只是加粗的那一段而已,這種影響要小得多。更重要的是,集群中緩存伺服器節點越多,增加節點帶來的影響越小


第一個 Ribbon 程式

創建名為 ribbon-provider 的項目,添加配置文件 application-01.properties 和 application-02.properties

# application-01.properties 配置文件內容
server.port=8080

# application-02.properties 配置文件內容
server.port=8081

開發 UserController 類

@RestController
@RequestMapping("user")
public class UserCon {

    @Resource
    private Environment environment;

    public String getPort() {
        return environment.getProperty("local.server.port");
    }

    @RequestMapping("getName")
    public String getUserName (){
        return "hello,ay" + "-" + getPort();
    }
}

通過使用不同的配置文件,可以啟動多個 SpringBoot 應用,分別啟動 ribbon-provider-8080 和 ribbon-provider-8081

創建名為 ribbon-consumer 的項目,pom.xml 添加依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

添加配置文件 application.yml

my-client:  #負載均衡配置
  ribbon:
    listOfServers: localhost:8080,localhost:8081  # 配置服務列表
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  # 配置負載均衡演算法 RoundRobinRule(輪詢)

Ribbon 的配置格式是 <clientName>:ribbon:需要配置的屬性<clientName> 是 Ribbon 的客戶端名稱,如果省略就配置所有客戶端,配置的屬性有以下幾種:

  • NFLoadBalancerClassName:配置 ILoadBalancer 的實現類
  • NFLoadBalancerRuleClassName:配置 IRule 的實現類
  • NFLoadBalancerPingClassName:配置 IPing 的實現類
  • NIWSServerListClassName:配置 ServerList 的實現類
  • NIWSServerListFilterClassName:配置 ServerListFilter 的實現類

在 main 方法中添加如下代碼:

@SpringBootApplication
public class RibbonConsumerApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(RibbonConsumerApplication.class, args);
        //獲取客戶端
        RestClient client = (RestClient) ClientFactory.getNamedClient("my-client");
        //調用UserController類的getUserName 方法
        HttpRequest request = HttpRequest.newBuilder().uri("/user/getName").build();
        //迴圈調用
        for(int i = 0; i<10; i++) {
            HttpResponse response = client.executeWithLoadBalancer(request);
            String result = response.getEntity(String.class);
            System.out.println(result);
        }
    }
}

啟動 ribbon-consumer 項目,從列印信息中可以看出,服務通過輪詢的方式調用


Ribbon 整合 Nacos & 自定義負載均衡策略

創建 ribbon-custom-consumer 的項目,添加配置類

@Configuration
public class RibbonConfig {

    @Bean
    public IRule ribbonRule() {
        // ribbon預設使用的是zoneAvoidanceRule規則,這裡修改為自定義方式
        return new MyRule();
    }
}

創建 MyRule 類,用來自定義負載均衡規則

/**
 * 負載規則:始終返回第一個服務
 */
public class MyRule extends AbstractLoadBalancerRule {

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object o) {
        ILoadBalancer loadBalancer = getLoadBalancer();
        // 獲取所有的服務
        List<Server> servers = loadBalancer.getAllServers();
        // 始終返回第一個服務
        return servers.get(0);
    }
}

自定義指定 Ribbon 客戶端的配置

/**
 * 使用 RibbonClient 為特定 name 的 Ribbon Client 自定義配置
 * 使用 @RibbonClient 的 configuration 屬性指定 Ribbon 的配置類
 */
@Configuration
@RibbonClient(name = "service-provider", configuration = RibbonConfig.class)
public class TestConfig {

}

在 application.properties 配置文件中添加如下配置

server.port=7089
spring.application.name=service-custom
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

在啟動類中添加 @EnableDiscoveryClient 註解

@EnableDiscoveryClient
@SpringBootApplication
public class RibbonCustomApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonCustomApplication.class, args);
    }
}

創建 TesController類,具體代碼如下

@RestController
@RequestMapping("test")
public class TestController {

    @Resource
    private LoadBalancerClient loadBalancerClient;

    @RequestMapping("getUserName")
    public String getUserName() {
        for (int i = 0; i < 20; i++) {
            //獲取service-provider服務
            ServiceInstance serviceInstance = loadBalancerClient.choose("service-provider");
            //列印當前選擇的是哪個節點
            System.out.println(serviceInstance.getServiceId() + serviceInstance.getHost() + "; " + serviceInstance.getPort());
        }
        return "hello,ay";
    }
}

在上述步驟中,我們創建了 ribbon-custom-consumer 項目,並定義了負載均衡規則 MyRule,服務啟動後註冊到 Nacos 中,這樣一來,在調用 getUserName 方法時,會從 Nacos 中獲取已註冊的服務提供者列表,並按照我們自定義的負載規則進行調用



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 問題描述 最近遇到一個有意思的問題,項目中有一個地方,點擊需要跳轉到一個新的功能變數名稱地址 筆者使用a標簽做跳轉,跳是跳過去了,可是跳過去以後,反而打不開了,顯示403佛伯樂 蛤? 大致這樣的代碼: <a href="http://abcdef ...
  • 本文來盤點微軟開源的十大前端項目,這些項目在 Github 上獲得了超過 45 萬 Star! Visual Studio Code Visual Studio Code 是一款由微軟開發的開源的代碼編輯器。它支持多種編程語言,如C、C++、C#、Python、JavaScript 和 TypeSc ...
  • 1.原始值和引用值 ECMScript變數包含兩種不同類型是數據:原始值和引用值。 原始值:最簡單的數據。有6中原始值:Undefined、Null、Boolean、Number、String和Symbol。原始值是按值訪問。 引用值:由多個值構成的對象。三大引用類型:1.object 2.Arra ...
  • 1、案例:猜數字 設置一個1-10之間的隨機數,然後輸入進行猜數字,猜的大了怎麼樣、猜的小了怎麼樣、猜對了怎麼樣 知識點:設置隨機數 、if判斷 、while迴圈 寫題思路: 1.設置彈框提出問題 2.定義一個隨機數0-10的數組 3.if 判斷 取值的範圍,在其範圍內反饋的結果 4.while迴圈 ...
  • 搭建後臺管理系統模板 2.1項目初始化 今天來帶大家從0開始搭建一個vue3版本的後臺管理系統。一個項目要有統一的規範,需要使用eslint+stylelint+prettier來對我們的代碼質量做檢測和修複,需要使用husky來做commit攔截,需要使用commitlint來統一提交規範,需要使 ...
  • Uber公司技術棧介紹 Uber(Uber Technologies,Inc.)中文譯作“優步”,是一家美國矽谷的科技公司。Uber在2009年,由加利福尼亞大學洛杉磯分校輟學生特拉維斯·卡蘭尼克和好友加勒特·坎普(Garrett Camp)創立。因旗下同名打車APP而名聲大噪。Uber已經進入中國 ...
  • 1. 定義通用返回結果類 ​ 定義ResultVO類,作返回給前端的對象結構,主要有4個欄位 code : 錯誤碼 data : 內容 message : 消息 description : 具體描述 import lombok.Data; import java.io.Serializable; / ...
  • 接上篇,當我們創建了很多類,比如 圖書館里的藏書,分社會科學類,藝術類、生活類、農業類、工業類等,而工業類又分為輕工業、重工業、信息工業,然後再細分。當分的越來越細時,程式就會越來越大。如何管理,便成了程式開發過程中一個重要的環節。於是可以按照圖書館分類管理的思想,對程式代碼進行管理。 將一個應用程 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...