負載均衡 —— 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 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...