平滑的加權輪詢均衡算法

前言

在反向代理、路由、分布式應用調度等場景中通常都需要用到負載均衡算法,負載均衡的關鍵要點是“均衡”,即確保調用請求能均衡地落到多個處理節點上,負載均衡算法一般使用隨機或輪詢都可以保證均衡性。

現實中由于服務器性能或資源分配的差異,導致我們需要為服務節點設置不同的權重,權重高的節點得到更多流量,同時降低低權重節點的流量比例。也即帶權重的均衡算法。

下面我們討論幾種常見的負載均衡算法,并針對其中一種給出完整的算法講解及實現。

一、隨機

這是最簡單的負載均衡算法,每次生成一個隨機數,然后對服務節點數進行取模,模值即為服務節點序號,很明顯這只能做到“均勻”,無法根據各服務節點的權重進行加權分配。不過略加調整即可實現加權分配:

構造一個范圍為總權重值的序列,然后用隨機數對總權重取模,模值所在區間即為對應的服務節點。譬如:有三個服務節點,其權重分別為:503020,則節點集圖像大致如下:

|<-----------A----------->|<-----B----->|<---C--->|

|<0--------------------50>|<51-------80>|<81--100>|

代碼簡示:

struct Node<TKey> where TKey : IEquatable<TKey>
{public Node(TKey key, int boundary) {this.Key = key;this.Boundary = boundary;}public TKey Key;public int Boundary;
}class NodeSelector
{int _total;Node<string> _nodes;void Initialize() {_total = 50 + 30 + 20;_nodes = new[] {new Node<string>("Node-A", 50),new Node<string>("Node-B", 50 + 30),new Node<string>("Node-C", 50 + 30 + 20),};}string Select() {var value = Randomizer.GenerateInt32() % _total;for(int i = 0; i < _nodes.Length; i++) {if(value <= _nodes[i].Boundary)return _nodes[i].Key;}return null;}
}

隨機算法的表現恰如其名,在一個甚至多個調度周期內也無法確保各節點的權重匹配度,只能在大樣本條件下滿足權重的概率分布,總之就兩字:隨緣。

二、一致哈希

關于一致性哈希算法的文章已經汗牛充棟,亦不是本文的重點,所以就不再贅述。在構建哈希環的時候需要依據服務節點的權重比來設置相應數量的虛擬節點,之后確定服務節點的算法與上述隨機算法基本差不多。

三、平滑加權輪詢

終于來到本文的重點部分,我們假設有三個服務節點,其權重分別為:421,那么在一個調度周期內,最簡單調度序列如:{A,A,A,A,B,B,C}{C,B,B,A,A,A,A}{B,B,C,A,A,A,A},但直覺這樣的調度順序不友好,因為它會在某一陣把壓力都落到同一個節點上,導致某個節點突然很忙的情況,類似汽車換擋的那種頓挫感。

如果調度序列變成:{A,B,A,C,A,B,A}{A,A,B,A,C,A,B} 這樣就顯得“平滑”和“均衡”多了,我們主要參考 Nginx 和 LVS 采用的兩種算法。

Nginx 算法

  • Nginx 的實現源碼:https://github.com/nginx/nginx/blob/52327e0627/src/http/ngx_http_upstream_round_robin.c

  • Nginx 的算法摘要:https://github.com/nginx/nginx/commit/52327e0627f49dbda1e8db695e63a4b0af4448b1

on?each?peer?selection?we?increase?current_weight?of?each?eligible?peer?by?its?weight,?select?peer?with?greatest?current_weight?and?reduce?its?urrent_weight?by?total?number?of?weight?points?distributed?among?peers.

算法詳解

  • 當前節點集初始值均為零:{0,0,0}

  • 所有節點的當前權重值加上設定的權重值

  • 在當前節點集中選取最大權重值的節點作為命中節點

  • 命中節點的當前權重值減去總權重值作為其新權重值,其他節點保持不變

ABC 三個節點的權重分別為:421,演算步驟如下:

步驟

選擇前當前值

選擇節點(命中)

選擇后當前值

1

{ 4, 2, 1}

A

{-3, 2, 1}

2

{ 1, 4, 2}

B

{ 1,-3, 2}

3

{ 5,-1, 3}

A

{-2,-1, 3}

4

{ 2, 1, 4}

C

{ 2, 1,-3}

5

{ 6, 3,-2}

A

{-1, 3,-2}

6

{ 3, 5,-1}

B

{ 3,-2,-1}

7

{ 7, 0, 0}

A

{ 0, 0, 0}

由上發現三個節點的命中次數符合 4:2:1,而且權重大的節點不會霸占選擇權。經過一個周期(7輪選擇)后,當前權重值又回到了{0, 0, 0},以上過程將按照周期進行循環,完全符合我們先前期望的平滑性。

數學證明

該算法的合理性和平滑性的數學證明:https://tenfy.cn/2018/11/12/smooth-weighted-round-robin

LVS 算法

Linux Virtual Server 采用的是另外一種,算法wiki文檔:http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling

從算法步驟和計算量上看,相對 Nginx 而言 LVS 算法略微簡單一些,性能可能會略好一點點(但都是同一個量級);通過模擬數據發現當節點權重差異較大時,其平滑性沒有 Nginx 算法好。

總結

在 Zongsoft.Data 數據訪問框架的讀寫分離中需要將讀寫操作路由到不同權重的數據庫,于是采用 Nginx 的平滑權重輪詢均衡算法實現了數據源路由選擇器,下面分別是平滑權重輪詢器和數據路由的代碼:

  • 平滑權重輪詢源碼:https://github.com/Zongsoft/Framework/blob/master/Zongsoft.Core/src/Components/Weighter.cs

  • 數據源權重選擇器:https://github.com/Zongsoft/Framework/blob/master/Zongsoft.Data/src/Common/DataSourceSelector.cs


參考資料

  • Nginx 平滑的基于權重輪詢算法分析

  • Nginx 負載均衡及算法分析

  • Nginx SWRR 算法解讀


提示:點擊“閱讀原文”以更舒適的姿勢閱覽本文。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282560.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282560.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282560.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php類精確驗證身份證號碼

<?php class check_IdCard {// $num為身份證號碼&#xff0c;$checkSex&#xff1a;1為男&#xff0c;2為女&#xff0c;不輸入為不驗證public function checkIdentity($num, $checkSex ) { // 不是15位或不是18位都是無效身份證號if (strlen($num) ! 15 && strl…

請說說接口和抽象類的區別?

1.從使用目的來看&#xff1a; 接口只是一個類間的協議&#xff0c;它并沒有規定怎么去實現&#xff1b; 抽象類可以重用你代碼使你的代碼更加簡潔&#xff1b;2.從行為來看&#xff1a; 接口可以多繼承,multi-implement 抽象類不能實例化&#xff0c;必須子類化才能實例化…

GitHub 使用

Git 是由 Linux 之父 Linus Tovalds 為了更好的管理 linux 內核開發而創立的分布是版本控制/軟件管理配置軟件. 簡單來說, Git 管理你的 代碼的歷史記錄 的工具. 首先注冊賬戶 (已經完成, moveofgod) 然后, 下載一個 GitHub Desktop(mac), msisgit 客戶端 (可以用命令行實現, …

LinkedHashMap 與 HashMap區別

2019獨角獸企業重金招聘Python工程師標準>>> LinkedHashMap 與 HashMap區別 &#xff08;非原創&#xff09; HashMap,LinkedHashMap,TreeMap都屬于Map Map 主要用于存儲鍵(key)值(value)對&#xff0c;根據鍵得到值&#xff0c;因此鍵不允許鍵重復,但允許值重復。 …

C# 11 中的 file local type

C# 11 中的 file local typeIntro在之前的版本中&#xff0c;我們想要一個類型只在當前的類型中生效&#xff0c;通常我們會在一個類的內部聲明一個 private 的類型以此來控制這個類型的訪問權限&#xff0c;在 C# 11 中引入了一個 file local type&#xff0c;僅在聲明類型的這…

PHP實現類似百度搜索自動完成(代碼簡單)

一、效果圖: 二、HTML代碼 <html lang"en"> <head><meta charset"utf-8"><title>jQuery UI 自動完成&#xff08;Autocomplete&#xff09; - 默認功能</title><link rel"stylesheet" href"/public/Auto…

Mysql讀寫分離php腳本

<?php/*php如何連接mysql*/ /*$link mysql_connect(‘localhost‘, ‘root‘, ‘‘);if (!$link) {die(‘Could not connect: ‘ . mysql_error());}echo ‘Connected successfully‘;mysql_close($link);*/ /*php如何選擇數據庫*//*$link mysql_connect(‘localhost‘, …

CentOS 搭建Postfix+Dovecot簡單郵件系統

2019獨角獸企業重金招聘Python工程師標準>>> 服務器信息 系統&#xff1a;CentOS 6.5 minimal版本 主機&#xff1a;虛擬機 虛擬機IP&#xff1a;192.168.128.128/24 宿主IP:10.1.79.24/24 安裝postfix 注意&#xff1a;CentOS 7實際上已經用postfixSasl2代替sendma…

Js獲取當前頁面URL各種參數

JS獲取當前頁面URL各種參數 一&#xff1a;Location Location 對象包含有關當前 URL 的信息。 Location 對象是 Window 對象的一個部分&#xff0c;可通過 window.location 屬性來訪問。 hash設置或返回從井號 (#) 開始的 URL&#xff08;錨&#xff09;。host設置或返回主機名…

php面試題2018

一 、PHP基礎部分 1、PHP語言的一大優勢是跨平臺&#xff0c;什么是跨平臺&#xff1f; PHP的運行環境最優搭配為ApacheMySQLPHP&#xff0c;此運行環境可以在不同操作系統&#xff08;例如windows、Linux等&#xff09;上配置&#xff0c;不受操作系統的限制&#xff0c;所以…

學生黨的專屬定制福利,你想要的這里全都有!

同學們&#xff1a;您好&#xff01;很?興認識?家&#xff01;我是微軟的 Regional Cloud Advocate Kinfey Lo&#xff0c;感謝您在課余時間打開這封信。踏??秋&#xff0c;技術峰會進?了旺季&#xff0c;有?向商業的&#xff0c;有?向開發者的&#xff0c;有?向技術社…

Quartus prime16.0 與modelsim ae 聯調

前言 quartus和modelsim聯調對仿真還是很方便的&#xff0c;當然最好是quartus干綜合到燒錄的活&#xff0c;modelsim單獨仿真。而且ae版的性能比se版差。 流程&#xff1a; 1.配置modelsim ae路徑&#xff1a; 我這里是這個路徑&#xff0c;根據你自己安裝的地方配置路徑。 2.…

30分鐘搞定后臺登錄界面(103個后臺PSD源文件、素材網站)

去年八月時要做一個OA系統為了后臺界面而煩惱&#xff0c;后來寫了一篇博客&#xff08;《后臺管理UI的選擇》&#xff09;介紹了選擇過程與常用后臺UI&#xff0c;令我想不到的時竟然有許多開發者與我一樣都為這個事情而花費不少時間&#xff0c;最后界面效果還是不佳&#xf…

分析拼多多的崛起【產品思維】

最近朋友圈討論拼多多上市的新聞大火&#xff0c;各有各的看法&#xff0c;很有意思&#xff0c;突然想起前段時間得到上的《梁寧-產品思維30講》&#xff0c;所以想從數據和產品角度分析分析拼多多的崛起。 一&#xff1a;拼多多的迅速崛起 我們先看看拼多多這幾年的成長歷程&…

62、滑動窗口的最大值

一、題目 給定一個數組和滑動窗口的大小&#xff0c;找出所有滑動窗口里數值的最大值。例如&#xff0c;如果輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小3&#xff0c;那么一共存在6個滑動窗口&#xff0c;他們的最大值分別為{4,4,6,6,6,5}&#xff1b; 針對數組{2,3,4,2,6,2,5…

KestrelServer詳解[2]: 網絡連接是如何創建的?

《KestrelServer詳解[1]&#xff1a;注冊監聽終結點&#xff08;Endpoint&#xff09;》已經詳細講述了如何使用KestrelServer&#xff0c;現在我們來簡單聊聊這種服務器的總體設計和實現原理。當KestrelServer啟動的時候&#xff0c;注冊的每個終結點將轉換成對應的“連接監聽…

PHP操作文件和目錄的相關函數

//判斷文件類型 filetype(a.php);//打開或創建文件 fopen(a.php,w);//讀取文件 fgets(a.php);//按行讀取 fread(a.php,1049);//按塊讀取 file_get_contents(a.php);//讀取文件//復制文件 copy(a.php,./b.php);//將a.php復制到b.php//刪除文件 unlink(b.php);//移動文件 rename(…

linux LyX中文編輯環境安裝配置指南-TeX可視化工具

TeX可以說是國際上排版的標準&#xff0c;尤其是論文、書籍之類&#xff0c;對公式的表現比MS辦公系列強的太多&#xff0c;格式異常優美&#xff0c;但是由于其比較復雜的命令&#xff0c;非可視化編輯&#xff0c;所以使得入門門檻較高&#xff0c;所以出現了LaTeX這樣的命令…

pandas DataFrame 數據處理常用操作

Xgboost調參&#xff1a; https://wuhuhu800.github.io/2018/02/28/XGboost_param_share/ https://blog.csdn.net/hx2017/article/details/78064362 pandas DataFrame中的空值處理&#xff1a; https://blog.csdn.net/yuanxiang01/article/details/78738812 pandas的DataFrame、…

redis集群報Jedis does not support password protected Redis Cluster configurations異常解決辦法...

解決spring-data-redis操作redis集群報“Jedis does not support password protected Redis Cluster configurations”的異常 原因&#xff1a;使用spring-data-redis操作redis集群時由于redis集群設置了密碼。 解決方案&#xff1a;升級spring-data-redis版本即可解決&#xf…