高效能負載均衡之演算法
昨天說的是ofollow,noindex">高效能負載均衡之分類架構
今天的內容可以說是昨天的擴充套件和補充,主要跟大家講將高效能負載均衡的演算法,高效能負載均衡演算法數量也不少,而且可以根據一些業務特性進行定製開發,拋開細節上的差異,根據演算法期望達到的目的,大體可以分為這麼幾類:
(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開始學架構》對我來說啟發還是頗多的,至少讓我瞭解架構設計原則和示例,以及常見的坑,當我進行架構設計時,我會參考他的一些想法和建議,當然了,凡是沒有絕對,最終的還是得結合實際情況。正如當年中國改革開放取得了很大成績,也是因為結合了自身的國情,避免重蹈蘇聯的覆轍。
另外關於架構,就我個人而言,我目前僅僅還只是一個菜鳥或者菜鳥都算不上,不過經過三個專案的改造和設計,吃了不少虧,也算是比小白要強點吧。
今天就寫到這了,北京的冬天越來越冷了,我也懶得出去玩,順便藉此機會好好提升自己。