高性能負載均衡之算法


昨天說的是高性能負載均衡之分類架構

今天的內容可以說是昨天的擴展和補充,主要跟大家講將高性能負載均衡的算法,高性能負載均衡算法數量也不少,而且可以根據一些業務特性進行定制開發,拋開細節上的差異,根據算法期望達到的目的,大體可以分為這么幾類:

(1)任務平分類:負載均衡系統將接收到的任務平均分配給服務器進行處理,這里的“平均”可以是絕對數量的平均,也可以是比例或者權重上的平均;

(2)負載均衡類:負載均衡系統根據服務器的負載來進行分配,這里的負載並不一定是通常意義上我們說的“CPU負載”,而是系統當前的壓力,可以用CPU負載來衡量,也可以用連接數、I/O使用率、網卡吞吐量等來衡量系統的壓力;

(3)性能最優類:負載均衡系統根據服務器的響應時間來進行任務分配,優先將新任務分配給響應最快的服務器;

(4)Hash類:負載均衡系統根據任務中的某些關鍵信息進行Hash運算,將相同Hash值的請求分配到統一台服務器上。常見的源地址Hahs、目標地址Hahs、session id hash、用戶IDHash等;

下面介紹一下負載均衡常用算法和它們的優缺點。

 

1.輪詢

負載均衡系統收到請求后,安卓順序輪流分配到服務器上。

輪詢是最簡單的一個策略,無需關注服務器本身的狀態,例如:

(1)某個服務器當前因為觸發了程序Bug進入了死循環導致CPU負載很高,負載均衡系統是不感知的,還是會繼續將請求源源不斷地發送給它;

(2)集群中有新的機器是32核的,老的機器是16核的,負載均衡系統也不是關注的,新老機器分配的任務數是一樣的;

需要注意的是負載均衡系統無須關注“服務器本身狀態”,這里的關鍵詞是“本身”。也就是說,只要服務器在運行,運行狀態是不關注的。但如果服務器直接宕機了,或者服務器和負載均衡系統斷連了,這時負載均衡系統是能夠感知的,也需要做出相應的處理。例如,將服務器從可分配服務器列表中刪除,否則就會出現服務器都宕機了,任務還不斷分配給它,這即不合理,又影響用戶使用的體驗。

輪詢的優點和缺點,用一個詞來表示,那就是“簡單”。

 

2.加權輪詢

負載均衡系統根據服務器權重進行任務分配,這里的權重一般是根據硬件配置進行靜態配置的,采用的動態的方式計算會更加契合業務,但復雜度也會更高。

加權輪詢是輪詢的一種特殊形式,其主要目的就是為了解決不同服務器處理能力有差異的問題。例如,前面的例子說到過集群中有新的機器是32核的,老的機器是16核的,那么理論上我們以假設新系統的處理能力是老機器的2倍,負載均衡系統就可以按照2:1的比例分配更多任務給新機器,從而充分利用新機器的性能。

加權輪詢解決了輪詢算法中無法根據服務器的配置差異進行任務分配問題,但同樣存在無法根據服務器的狀態差異進行任務分配的問題。

 

3.負載均衡最低優先

負載均衡系統將任務分配給當前負載最低的服務器,這里的負載根據不同的任務類型和業務場景,可以用不同的指標來衡量。

例如:

(1)Nginx這種7層網絡負載系統,可以以“HTTP請求數”來判斷服務器狀態(Nginx內置的負載均衡算法不支持這種方式,需要進行擴展);

(2)LVS這種4層網站負載設備,可以以“連接數”來判斷服務器的狀態,服務器連接數越大,表明服務器壓力越大;

(3)如果我們自己開發負載均衡系統,可以根據業務特點來選擇指標衡量系統壓力。如果是CPU密集型,可以以“CPU負載”來衡量系統壓力;如果是I/O密集型,可以以“I/O負載”來衡量系統壓力;

 

負載最低優先的算法解決了輪詢算法中無法感知服務器狀態的問題,由此帶來的代價是復雜度要增加很多。例如:

(1)最少連接數優先的算法要求負載均衡系統統計每個服務器當前建立的連接,其應用場景僅限於負載均衡接收的任何連接請求都會轉發給服務器進行處理,否則,如果負載均衡系統和服務器之間是固定的連接池方式,就不適合采取這種算法。例如,LVS可以采取這種算法進行負載均衡,而一個通過連接池的方式連接MySQL集群的負載均衡系統就不適合采取這種算法進行負載均衡;

(2)CPU最低優先的算法要求負載均衡系統以某種方式手機每個服務器的CPU負載,而且要確定是以1分鍾的負載為標准,還是以15分鍾的負載為標准,不存在1分鍾肯定比15分鍾要好或者要差。不同業務最優的時間間隔是不一樣的,時間間隔太短容易造成頻繁波動,時間間隔太長又可能造成峰值來臨時響應緩慢。

負載均衡最低優先算法基本上能夠比較完美地解決輪詢算法的缺點,因為采用這種算法后,負載均衡系統需要感知服務器當前的運行狀態。當然,其代價是復雜度大幅上升。通俗來講,輪詢可能是5行代碼就能實現的算法(其實JS的定時任務就能做好,同樣Spring的定時任務也能),而負載最低優先算法可能要1000行才能實現,甚至需要負載均衡系統和服務器都要開發代碼。負載最低優先算法如果本身沒有設計好,或者不適合業務的運行特點,算法本身就可能成為性能的瓶頸,或者引發很多莫名其妙的問題。所以負載最低優先算法雖然效果看起來美好,但實際上真正應用的場景反而沒有輪詢(包括加權輪詢)那么多。

 

4.性能最優類

負載最低優先類算法是站在服務器的角度來進行分配的,而性能最優優先類算法則是站在客戶端的角度進行分配的,優先將任務分配給處理速度最快的服務器,通過這種方式達到最快響應客戶端的目的。

和負載最低優先類算法類似,性能最優優先類算法本質上也是感知了服務器的狀態,只是通過響應時間這個外部標准來衡量服務器狀態而已。因此性能最優優先類算法存在的問題和負載最低優先類算法類似,復雜度都很高,主要體現在:

(1)負載均衡系統需要收集和分析每個服務器每個任務的響應時間,在大量任務處理的場景下,這種收集和統計本身也會收集較多的性能;

(2)為了減少這種統計上的消耗,可以采取采樣的方式來統計,即不統計所有任務的響應時間,而是抽樣統計部分任務的響應時間來估算整體任務的響應時間。采樣統計

雖然能夠減少性能消耗,但使得復雜度進一步提升,因為要確定合適的采樣率,采樣率太低會導致結果不准確,采樣率太高會導致性能消耗較大,找到合適的采樣率是一件復雜的事情;

(3)無論是全部統計還是采樣統計,都需要選擇合適的周期:是10秒內性能最優,還是1分鍾內性能最優,還是5分鍾內性能最優,需要根據實際業務進行判斷和選擇,同時這也是一件比較復雜的事情,甚至出現系統上線后需要不斷調優才能達到最優設計;

 

5.Hash類

負載均衡系統根據任務中的某些關鍵信息進行Hash運算,將相同Hahs值的請求分配到同一台服務器上,這樣做的目的主要為了滿足特定的業務需求。

 

(1)源地址Hash

將來源於同一個源IP地址的任務分配給同一個服務器進行處理,適合於存在事務、會話的業務。例如,當我們通過瀏覽器登錄網上銀行時,會生成一個會話信息,這個會話是臨時的,關閉瀏覽器后就失效。網上銀行后台無須持久化會話信息,只需要在某台服務器上臨時保存這個會話就可以了,但需要保證用戶在會話存在期間,每次都能訪問到同一個服務器,這種業務場景就可以用源地址Hash來實現。

 

(2)ID Hash

將某個ID標識的業務分配到同一個服務器中進行處理,這里的ID一般是臨時性數據的ID(如session id)。例如,上述的網上銀行登錄的例子,用session id hash同樣可以實現同一個會話期間,用戶每次訪問到同一台服務器的目的。

 

小結:

上面講的五種負載均衡通常涉及到的算法,目前的話,我涉及到也就是第二種。第一種雖然簡單,但是風險太高了。第三種和第四種及其第五種今天我也是剛接觸到學習的。

本文主要參考李運華的《從0開始學架構》。

另外在補充一點,有不少朋友買着專欄,剛開始會看一點,后來就不看了,抱着反正已經買了,早看晚看都是看,最終的情況很少有人會去看,這也是一些付費專欄抓到的商機。

其實李運華《從0開始學架構》對我來說啟發還是頗多的,至少讓我了解架構設計原則和示例,以及常見的坑,當我進行架構設計時,我會參考他的一些想法和建議,當然了,凡是沒有絕對,最終的還是得結合實際情況。正如當年中國改革開放取得了很大成績,也是因為結合了自身的國情,避免重蹈蘇聯的覆轍。

另外關於架構,就我個人而言,我目前僅僅還只是一個菜鳥或者菜鳥都算不上,不過經過三個項目的改造和設計,吃了不少虧,也算是比小白要強點吧。

今天就寫到這了,北京的冬天越來越冷了,我也懶得出去玩,順便借此機會好好提升自己。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM