漫談負載均衡

木可大大發表於2019-03-01

負載均衡是什麼鬼?從字面意思來看,它應該有兩層意思分別是負載和均衡。而對於系統負載均衡它同樣具有兩層意思,其中系統負載指的系統能夠承載的最大訪問流量,系統均衡指的是前端請求要均勻地分配給後端機器,同時,同一使用者要儘可能分配給同一機器。系統通過負載均衡以後具有如下好處:

1、避免資源浪費。如果我們均衡演算法選的不好,就會導致後端資源浪費。比如:如果選擇一致Hash演算法,可以很好利用cache的容量。而如果用隨機,有可能會讓cache效果大打折扣。

2、避免服務不可用。當我們不考慮系統的承載能力,有可能直接把某臺機器壓垮,比如當機器的CPU利用率達到80%,如果再有大量的請求,那麼該機器直接當機,甚至於導致雪崩情況(一臺機器當機,對應的請求會分給其他機器上,那麼其他機器也會出現當機,以至於全部機器都當機)。

理論基礎

系統要實現負載均衡,背後肯定需要一些演算法支撐,下面就來看下對應的演算法。

1、負載演算法

既然要解決後端系統的承載能力,那我們就有很多方式,常用的有以下幾種:

靜態配置

這種方式對於中小系統來講是最有效最穩定的。因為後端機器的效能配置、上面部署哪些服務,還能有多大的承載能力等等,我們是最清楚的。比如,我們經常看到nginx的配置:

image

動態調整

當碰到機器故障,以及由於效能問題無法處理請求時,如果此時還將新來的請求分配到該節點,那麼可能導致該節點當機。因此,根據節點的實際負載動態調整節點的權重是非常重要的。當然,要得到節點的真正負載,以及如何定義負載,無論負載是否及時收集,都是需要考慮的問題。

動態調整首先計算所有節點的請求響應時間,對於響應較快的節點,我們可以多分配請求給它,然後增加它的請求數,當它的響應變慢時再慢慢減少它的請求數,慢慢地我們找到這個節點最佳平衡點,即分配多少請求給它。通過相同方法我們找到所有節點的平衡點。

這種方法的好處在於可以動態平衡後面伺服器的處理能力。不過,任何事物都有兩面性。這種方案如果遇到極端情況,可能會造成雪崩。當某臺機器出現短暫網路抖動的時候,它的響應就可能變慢,這個時候,前端服務就會將它的請求分配給其他機器。如果分配的很多,就有可能造成某些機器響應也變慢。然後又將這些機器的請求分配給另外機器。如此這般,就會造成雪崩。

2、均衡演算法

均衡演算法主要解決將請求如何傳送給後端服務。經常會用到以下三種演算法:隨機(random)、輪詢(round-robin)和 雜湊演算法。

隨機演算法

隨機演算法就是通過一個隨機函式將所有請求分散到各個節點上, 該方法比較簡單,且能做到將請求均勻地分散到各個節點上,因此經常使用隨機演算法。

輪詢演算法

輪詢演算法就是將所有節點以同樣的概率向外提供服務,但是它沒有考慮各個節點之間的效能差別,對於同樣數目的請求,效能好的節點能夠輕鬆完成,而效能差的節點完成的比較費力。因此,我們提出了加權輪詢演算法,為不同效能的節點賦予不同權重。

雜湊演算法

通常將使用者 id 或 ip 作為key,計算出對應的hash值,然後再對節點數量取模,即hash(key) mode n,其中n為節點數,得到該使用者請求落到哪個節點上。該方法可以做到讓同一個請求落到同一個節點中,但是當節點數量發生動態變化時,該方法就不太適應了。此時,就應該使用一致性hash演算法。一致性hash演算法就是把每臺server分成v個虛擬節點,再把所有虛擬節點(n*v)隨機分配到一致性雜湊的圓環上,這樣所有的使用者從自己圓環上的位置順時針往下取到第一個vnode就是自己所屬的節點。當此節點存在故障時,再順時針取下一個作為替代節點。更加具體的描述可以參考一致性Hash這篇文章,這裡就不展開了。

具體實現

目前負載均衡系統有Nginx、LVS、F5,其總會難過Nginx是軟體的7層負載均衡,LVS是核心的4層負載均衡,F5是硬體的4層負載均衡。

軟體和硬體的區別在於效能,硬體遠遠高於軟體,Nginx的效能是萬級的,一般的Linux伺服器上安裝一個Nginx能達到每秒5萬併發請求;而F5的效能能達到百萬級,從200萬每秒到800萬每秒都有,不過價格很貴。

4層和7層的區別在於協議和靈活性,Nginx是7層的,它支援HTTP等協議,而LVS和F5是4層協議,它們和協議無關,幾乎所有應用都可以做。

image

image

歡迎關注微信公眾號:木可大大,所有文章都將同步在公眾號上。

相關文章