大廠微服務架構的負載均衡算法原來都這麼選型的!

1 負載均衡的產生

假設你訂閱了一個別人的服務,從註冊中心查詢獲得了這個服務的可用節點列表,而這個列表裏包含了幾十個節點,這個時候你該選擇哪一個節點發起調用呢?這就是客戶端負載均衡算法的問題。算法

2 負載均衡算法的意義

  • 考慮調用的均勻性,也就是要讓每一個節點都接收到調用,發揮全部節點的做用
  • 考慮調用的性能,也就是哪一個節點響應最快,優先調用哪一個節點

不一樣負載均衡算法也就是在這兩個方面的考慮不一樣。數組

3 常見的負載均衡算法

random(隨機)

dubbo默認。 從可用的服務節點中,隨機挑選一個節點來訪問。 實現時,隨機算法一般經過生成一個隨機數來實現,好比服務有10個節點,那麼就每一次生成一個1~10之間的隨機數,假設生成的是2,那麼就訪問編號爲2的節點。 採用隨機算法,在節點數量足夠多,而且訪問量比較大的狀況下,各個節點被訪問的機率基本相同。緩存

適用場景

實現簡單,在請求量遠超可用服務節點數量的狀況下,各個服務節點被訪問的機率基本相同,主要應用在各個服務節點的性能差別不大時。markdown

roundrobin(輪詢)

均勻地將流量打到各個機器上去,但若是各個機器的性能不同,容易致使性能差的機器負載太高。因此此時須要調整權重,讓性能差的機器承載權重小一些,流量少一些。網絡

按固定順序,把可用的服務節點,挨個訪問一次。負載均衡

適用場景

相似隨機算法,各個服務節點被訪問的機率也基本相同,也主要應用在各個服務節點性能差別不大。dom

實現

一般把全部可用節點放到一個數組,挨個訪問。好比服務有10個節點,放到數組裏就是一個大小爲10的數組,這樣的話就能夠從序號爲0的節點開始訪問,訪問後序號自動加1,下一次就會訪問序號爲1的節點,以此類推。分佈式

輪詢算法能保證全部節點被訪問到的機率相同。一個輪詢算法的代碼實現,能夠參考這個示例。ide

加權輪詢

輪詢可以保證全部節點被訪問的機率相同,而加權輪詢算法是在此基礎上,給每一個節點賦予一個權重,從而使每一個節點被訪問到的機率不一樣,權重大的節點被訪問的機率就高,權重小的節點被訪問的機率就小。函數

實現

加權輪詢算法是生成一個節點序列,該序列裏有n個節點,n是全部節點的權重之和。在這個序列中,每一個節點出現的次數,就是它的權重值。好比有三個節點:a、b、c,權重分別是三、二、1,那麼生成的序列就是{a、a、b、c、b、a},這樣的話按照這個序列訪問,前6次請求就會分別訪問節點a三次,節點b兩次,節點c一次。從第7個請求開始,又從新按照這個序列的順序來訪問節點。

要儘量保證生產的序列的均勻,若是生成的不均勻會形成節點訪問失衡,好比剛纔的例子,若是生成的序列是{a、a、a、b、b、c},就會致使前3次訪問的節點都是a。

適用場景

主要用在服務節點性能差別比較大的狀況。好比新的服務節點的性能每每要高於舊的節點,這個時候能夠給新的節點設置更高的權重,讓它承擔更多的請求,充分發揮新節點的性能優點。

leastactive(最少活躍鏈接)

自動感知一下,若是某個機器性能越差,那麼接收的請求越少,越不活躍,此時就會給不活躍的性能差的機器更少的請求

每次訪問都選擇鏈接數最少的節點。由於不一樣節點處理請求的速度不一樣,使得同一個服務消費者同每個節點的鏈接數都不相同。鏈接數大的節點,能夠認爲是處理請求慢,而鏈接數小的節點,能夠認爲是處理請求快。因此在挑選節點時,能夠以鏈接數爲依據,選擇鏈接數最少的節點訪問。

在實現時,須要記錄跟每個節點的鏈接數,這樣在選擇節點時,才能比較出鏈接數最小的節點。

適用場景

客戶端同服務端節點的鏈接數是在時刻變化的,理論上鍊接數越少表明此時服務端節點越空閒,選擇最空閒的節點發起請求,能獲取更快的響應速度。 特別是當:

  • 服務端節點性能差別較大
  • 很差作到預先定義權重

採用該算法很不錯。

consistanthash(一致性 hash)

一致性Hash算法,相同參數的請求必定分發到一個provider上去,provider掛掉的時候,會基於虛擬節點均勻分配剩餘的流量,抖動不會太大。

經過某個hash函數,把同一個來源的請求都映射到同一個節點上。 同一個來源的請求,只會映射到同一個節點上,能夠說是具備記憶功能,不會有分佈式會話的困擾。只有當該節點不可用時,請求才會被分配到相鄰的可用節點上。

適用場景

若是你須要的不是隨機負載均衡,是要一類請求都到一個節點,那就走這個一致性hash策略。

由於它可以保證同一個客戶端的請求始終訪問同一個服務節點,因此適合服務端節點處理不一樣客戶端請求差別較大的場景。好比服務端緩存裏保存着客戶端的請求結果,若是同一客戶端一直訪問一個服務節點,那麼就能夠一直從緩存中獲取數據。

這五種負載均衡算法是業界最經常使用的,不光在RPC調用中被普遍採用,在一些負載均衡組件好比Nginx中也有應用,因此說是一種通用的負載均衡算法,可是不是全部的業務場景都能很好解決呢?

若是:

  • 服務節點數量衆多,且性能差別比較大
  • 服務節點列表常常發生變化,增長節點或者減小節點時有發生
  • 客戶端和服務節點之間的網絡狀況比較複雜,有些在一個數據中心,有些不在一個數據中心須要跨網訪問,並且網絡常常延遲或者抖動

這時:

  • 隨機、輪詢,第一個狀況就不知足
  • 加權須要預先配置服務節點的權重,在節點列表常常變化的狀況下很差維護,因此也不適合
  • 最少活躍鏈接算法是從客戶端自身維度去判斷的,在實際應用時,並不能直接反映出服務節點的請求量大小,尤爲是在網絡狀況比較複雜的狀況下,並不能作到動態的把請求發送給最合適的服務節點
  • 一致性hash顯然也不適合這種場景

針對上面這種場景,有一種算法更加適合,這種算法就是

自適應最優選擇算法

在客戶端本地維護一份同每個服務節點的性能統計快照,每隔一段時間更新該快照。 發起請求時,根據「二八原則」,把服務節點分紅兩部分,找出20%響應最慢的節點,下降權重。這樣客戶端就可以實時的根據自身訪問每一個節點性能的快慢,動態調整訪問最慢的那些節點的權重,來減小訪問量,從而能夠優化長尾請求。

自適應最優選擇算法是對加權輪詢算法的改良,能夠看做是一種動態加權輪詢算法:

  • 每隔一段時間獲取客戶端同每一個服務節點之間調用的平均性能統計

須要在內存中開闢一塊空間記錄客戶端同每個服務節點之間調用的平均性能,並每隔一段固定時間去更新。這個更新的時間間隔不能過短,過短的話很容易受瞬時的性能抖動影響,致使統計變化太快,沒有參考性;同時也不能太長,太長的話時效性就會大打折扣,效果不佳。根據個人經驗,1分鐘的更新時間間隔是個比較合適的值。

  • 按這個性能統計對服務節點進行排序,對排在性能倒數20%的那部分節點賦予一個較低的權重,其他的節點賦予正常的權重

關鍵是設定權重值,即便服務節點之間的性能差別較大,也不適合把權重設置得差別太大,可能致使性能較好的節點與性能較差的節點之間調用量相差太大,這樣也不是一種合理的狀態。在實際設定時,能夠設置20%性能較差的節點權重爲3,其他節點權重爲5。

這些都屬於軟件層面的負載均衡算法。

相關文章
相關標籤/搜索