負(fù)載均衡分類
常見的負(fù)載均衡系統(tǒng)包括3種:DNS負(fù)載均衡、硬件負(fù)載均衡和軟件負(fù)載均衡。DNS是最簡單也是最常見的負(fù)載均衡方式,一般用來實現(xiàn)地理級別的均衡。例如,北方的用戶訪問北京的機房,南方的用戶訪問深圳的機房。DNS負(fù)載均衡的本質(zhì)是DNS解析同一個域名可以返回不同的IP地址。例如,同樣是www.baidu.com,北方用戶解析后獲取的地址是61.135.165.224(這是北京機房的IP),南方用戶解析后獲取的地址是14.215.177.38(這是深圳機房的IP)。下面是DNS負(fù)載均衡的簡單示意圖:
DNS負(fù)載均衡實現(xiàn)簡單、成本低,但也存在粒度太粗、負(fù)載均衡算法少等缺點。仔細(xì)分析一下優(yōu)缺點,其優(yōu)點有:
? 簡單、成本低:負(fù)載均衡工作交給DNS服務(wù)器處理,無須自己開發(fā)或者維護(hù)負(fù)載均衡設(shè)備。
? 就近訪問,提升訪問速度:DNS解析時可以根據(jù)請求來源IP,解析成距離用戶最近的服務(wù)器地址,可以加快訪問速度,改善性能。
缺點有:
? 更新不及時:DNS緩存的時間比較長,修改DNS配置后,由于緩存的原因,還是有很多用戶會繼續(xù)訪問修改前的IP,這樣的訪問會失敗,達(dá)不到負(fù)載均衡的目的,并且也影響用戶正常使用業(yè)務(wù)。
? 擴(kuò)展性差:DNS負(fù)載均衡的控制權(quán)在域名商那里,無法根據(jù)業(yè)務(wù)特點針對其做更多的定制化功能和擴(kuò)展特性。
? 分配策略比較簡單:DNS負(fù)載均衡支持的算法少;不能區(qū)分服務(wù)器的差異(不能根據(jù)系統(tǒng)與服務(wù)的狀態(tài)來判斷負(fù)載);也無法感知后端服務(wù)器的狀態(tài)。
針對DNS負(fù)載均衡的一些缺點,對于時延和故障敏感的業(yè)務(wù),有一些公司自己實現(xiàn)了HTTP-DNS的功能,即使用HTTP協(xié)議實現(xiàn)一個私有的DNS系統(tǒng)。這樣的方案和通用的DNS優(yōu)缺點正好相反。
硬件負(fù)載均衡
硬件負(fù)載均衡是通過單獨的硬件設(shè)備來實現(xiàn)負(fù)載均衡功能,這類設(shè)備和路由器、交換機類似,可以理解為一個用于負(fù)載均衡的基礎(chǔ)網(wǎng)絡(luò)設(shè)備。目前業(yè)界典型的硬件負(fù)載均衡設(shè)備有兩款:F5和A10。這類設(shè)備性能強勁、功能強大,但價格都不便宜,一般只有“土豪”公司才會考慮使用此類設(shè)備。普通業(yè)務(wù)量級的公司一是負(fù)擔(dān)不起,二是業(yè)務(wù)量沒那么大,用這些設(shè)備也是浪費。
硬件負(fù)載均衡的優(yōu)點是:
? 功能強大:全面支持各層級的負(fù)載均衡,支持全面的負(fù)載均衡算法,支持全局負(fù)載均衡。
? 性能強大:對比一下,軟件負(fù)載均衡支持到10萬級并發(fā)已經(jīng)很厲害了,硬件負(fù)載均衡可以支持100萬以上的并發(fā)。
? 穩(wěn)定性高:商用硬件負(fù)載均衡,經(jīng)過了良好的嚴(yán)格測試,經(jīng)過大規(guī)模使用,穩(wěn)定性高。
? 支持安全防護(hù):硬件均衡設(shè)備除具備負(fù)載均衡功能外,還具備防火墻、防DDoS攻擊等安全功能。
硬件負(fù)載均衡的缺點是:
? 價格昂貴:最普通的一臺F5就是一臺“馬6”,好一點的就是“Q7”了。
? 擴(kuò)展能力差:硬件設(shè)備,可以根據(jù)業(yè)務(wù)進(jìn)行配置,但無法進(jìn)行擴(kuò)展和定制。
軟件負(fù)載均衡
軟件負(fù)載均衡通過負(fù)載均衡軟件來實現(xiàn)負(fù)載均衡功能,常見的有Nginx和LVS,其中Nginx是軟件的7層負(fù)載均衡,LVS是Linux內(nèi)核的4層負(fù)載均衡。4層和7層的區(qū)別就在于協(xié)議和靈活性,Nginx支持HTTP、E-mail協(xié)議;而LVS是4層負(fù)載均衡,和協(xié)議無關(guān),幾乎所有應(yīng)用都可以做,例如,聊天、數(shù)據(jù)庫等。軟件和硬件的最主要區(qū)別就在于性能,硬件負(fù)載均衡性能遠(yuǎn)遠(yuǎn)高于軟件負(fù)載均衡性能。Ngxin的性能是萬級,一般的Linux服務(wù)器上裝一個Nginx大概能到5萬/秒;LVS的性能是十萬級,據(jù)說可達(dá)到80萬/秒;而F5性能是百萬級,從200萬/秒到800萬/秒都有(數(shù)據(jù)來源網(wǎng)絡(luò),僅供參考,如需采用請根據(jù)實際業(yè)務(wù)場景進(jìn)行性能測試)。當(dāng)然,軟件負(fù)載均衡的最大優(yōu)勢是便宜,一臺普通的Linux服務(wù)器批發(fā)價大概就是1萬元左右,相比F5的價格,那就是自行車和寶馬的區(qū)別了。除了使用開源的系統(tǒng)進(jìn)行負(fù)載均衡,如果業(yè)務(wù)比較特殊,也可能基于開源系統(tǒng)進(jìn)行定制(例如,Nginx插件),甚至進(jìn)行自研。
軟件負(fù)載均衡的優(yōu)點:
? 簡單:無論是部署還是維護(hù)都比較簡單。
? 便宜:只要買個Linux服務(wù)器,裝上軟件即可。
? 靈活:4層和7層負(fù)載均衡可以根據(jù)業(yè)務(wù)進(jìn)行選擇;也可以根據(jù)業(yè)務(wù)進(jìn)行比較方便的擴(kuò)展,例如,可以通過Nginx的插件來實現(xiàn)業(yè)務(wù)的定制化功能。
其實下面的缺點都是和硬件負(fù)載均衡相比的,并不是說軟件負(fù)載均衡沒法用。
? 性能一般:一個Nginx大約能支撐5萬并發(fā)。
? 功能沒有硬件負(fù)載均衡那么強大。
? 一般不具備防火墻和防DDoS攻擊等安全功能。
負(fù)載均衡典型架構(gòu)
前面我們介紹了3種常見的負(fù)載均衡機制:DNS負(fù)載均衡、硬件負(fù)載均衡、軟件負(fù)載均衡,每種方式都有一些優(yōu)缺點,但并不意味著在實際應(yīng)用中只能基于它們的優(yōu)缺點進(jìn)行非此即彼的選擇,反而是基于它們的優(yōu)缺點進(jìn)行組合使用。具體來說,組合的基本原則為:
? DNS負(fù)載均衡用于實現(xiàn)地理級別的負(fù)載均衡;
? 硬件負(fù)載均衡用于實現(xiàn)集群級別的負(fù)載均衡;
? 軟件負(fù)載均衡用于實現(xiàn)機器級別的負(fù)載均衡。
以一個假想的實例來說明一下這種組合方式,如下圖所示。
整個系統(tǒng)的負(fù)載均衡分為三層
? 地理級別負(fù)載均衡:www.xxx.com部署在北京、廣州、上海三個機房,當(dāng)用戶訪問時,DNS會根據(jù)用戶的地理位置來決定返回哪個機房的IP,圖中返回了廣州機房的IP地址,這樣用戶就訪問到廣州機房了。
? 集群級別負(fù)載均衡:廣州機房的負(fù)載均衡用的是F5設(shè)備,F(xiàn)5收到用戶請求后,進(jìn)行集群級別的負(fù)載均衡,將用戶請求發(fā)給3個本地集群中的一個,我們假設(shè)F5將用戶請求發(fā)給了“廣州集群2”。
? 機器級別的負(fù)載均衡:廣州集群2的負(fù)載均衡用的是Nginx,Nginx收到用戶請求后,將用戶請求發(fā)送給集群里面的某臺服務(wù)器,服務(wù)器處理用戶的業(yè)務(wù)請求并返回業(yè)務(wù)響應(yīng)。
需要注意的是,上圖只是一個示例,一般在大型業(yè)務(wù)場景下才會這樣用,如果業(yè)務(wù)量沒這么大,則沒有必要嚴(yán)格照搬這套架構(gòu)。例如,一個大學(xué)的論壇,完全可以不需要DNS負(fù)載均衡,也不需要F5設(shè)備,只需要用Nginx作為一個簡單的負(fù)載均衡就足夠了。
負(fù)載均衡算法
負(fù)載均衡算法數(shù)量較多,而且可以根據(jù)一些業(yè)務(wù)特性進(jìn)行定制開發(fā),拋開細(xì)節(jié)上的差異,根據(jù)算法期望達(dá)到的目的,大體上可以分為下面幾類。
? 任務(wù)平分類:負(fù)載均衡系統(tǒng)將收到的任務(wù)平均分配給服務(wù)器進(jìn)行處理,這里的“平均”可以是絕對數(shù)量的平均,也可以是比例或者權(quán)重上的平均。
? 負(fù)載均衡類:負(fù)載均衡系統(tǒng)根據(jù)服務(wù)器的負(fù)載來進(jìn)行分配,這里的負(fù)載并不一定是通常意義上我們說的“CPU負(fù)載”,而是系統(tǒng)當(dāng)前的壓力,可以用CPU負(fù)載來衡量,也可以用連接數(shù)、I/O使用率、網(wǎng)卡吞吐量等來衡量系統(tǒng)的壓力。
? 性能最優(yōu)類:負(fù)載均衡系統(tǒng)根據(jù)服務(wù)器的響應(yīng)時間來進(jìn)行任務(wù)分配,優(yōu)先將新任務(wù)分配給響應(yīng)最快的服務(wù)器。
? Hash類:負(fù)載均衡系統(tǒng)根據(jù)任務(wù)中的某些關(guān)鍵信息進(jìn)行Hash運算,將相同Hash值的請求分配到同一臺服務(wù)器上。常見的有源地址Hash、目標(biāo)地址Hash、session id hash、用戶ID Hash等。接下來介紹一下負(fù)載均衡算法以及它們的優(yōu)缺點。
輪詢
負(fù)載均衡系統(tǒng)收到請求后,按照順序輪流分配到服務(wù)器上。輪詢是最簡單的一個策略,無須關(guān)注服務(wù)器本身的狀態(tài),例如:
? 某個服務(wù)器當(dāng)前因為觸發(fā)了程序bug進(jìn)入了死循環(huán)導(dǎo)致CPU負(fù)載很高,負(fù)載均衡系統(tǒng)是不感知的,還是會繼續(xù)將請求源源不斷地發(fā)送給它。
? 集群中有新的機器是32核的,老的機器是16核的,負(fù)載均衡系統(tǒng)也是不關(guān)注的,新老機器分配的任務(wù)數(shù)是一樣的。
需要注意的是負(fù)載均衡系統(tǒng)無須關(guān)注“服務(wù)器本身狀態(tài)”,這里的關(guān)鍵詞是“本身”。也就是說,只要服務(wù)器在運行,運行狀態(tài)是不關(guān)注的。但如果服務(wù)器直接宕機了,或者服務(wù)器和負(fù)載均衡系統(tǒng)斷連了,這時負(fù)載均衡系統(tǒng)是能夠感知的,也需要做出相應(yīng)的處理。例如,將服務(wù)器從可分配服務(wù)器列表中刪除,否則就會出現(xiàn)服務(wù)器已經(jīng)宕機了,任務(wù)還不斷地分配給它,這明顯是不合理的??偠灾?,“簡單”是輪詢算法的優(yōu)點,也是它的缺點。
加權(quán)輪詢
負(fù)載均衡系統(tǒng)根據(jù)服務(wù)器權(quán)重進(jìn)行任務(wù)分配,這里的權(quán)重一般是根據(jù)硬件配置進(jìn)行靜態(tài)配置的,采用動態(tài)的方式計算會更加契合業(yè)務(wù),但復(fù)雜度也會更高。加權(quán)輪詢是輪詢的一種特殊形式,其主要目的就是為了解決不同服務(wù)器處理能力有差異的問題。例如,集群中有新的機器是32核的,老的機器是16核的,那么理論上我們可以假設(shè)新機器的處理能力是老機器的2倍,負(fù)載均衡系統(tǒng)就可以按照2:1的比例分配更多的任務(wù)給新機器,從而充分利用新機器的性能。加權(quán)輪詢解決了輪詢算法中無法根據(jù)服務(wù)器的配置差異進(jìn)行任務(wù)分配的問題,但同樣存在無法根據(jù)服務(wù)器的狀態(tài)差異進(jìn)行任務(wù)分配的問題。
負(fù)載最低優(yōu)先
負(fù)載均衡系統(tǒng)將任務(wù)分配給當(dāng)前負(fù)載最低的服務(wù)器,這里的負(fù)載根據(jù)不同的任務(wù)類型和業(yè)務(wù)場景,可以用不同的指標(biāo)來衡量。例如:
? LVS這種4層網(wǎng)絡(luò)負(fù)載均衡設(shè)備,可以以“連接數(shù)”來判斷服務(wù)器的狀態(tài),服務(wù)器連接數(shù)越大,表明服務(wù)器壓力越大。
? Nginx這種7層網(wǎng)絡(luò)負(fù)載系統(tǒng),可以以“HTTP請求數(shù)”來判斷服務(wù)器狀態(tài)(Nginx內(nèi)置的負(fù)載均衡算法不支持這種方式,需要進(jìn)行擴(kuò)展)。
? 如果我們自己開發(fā)負(fù)載均衡系統(tǒng),可以根據(jù)業(yè)務(wù)特點來選擇指標(biāo)衡量系統(tǒng)壓力。如果是CPU密集型,可以以“CPU負(fù)載”來衡量系統(tǒng)壓力;如果是I/O密集型,可以以“I/O負(fù)載”來衡量系統(tǒng)壓力。負(fù)載最低優(yōu)先的算法解決了輪詢算法中無法感知服務(wù)器狀態(tài)的問題,由此帶來的代價是復(fù)雜度要增加很多。例如:
? 最少連接數(shù)優(yōu)先的算法要求負(fù)載均衡系統(tǒng)統(tǒng)計每個服務(wù)器當(dāng)前建立的連接,其應(yīng)用場景僅限于負(fù)載均衡接收的任何連接請求都會轉(zhuǎn)發(fā)給服務(wù)器進(jìn)行處理,否則如果負(fù)載均衡系統(tǒng)和服務(wù)器之間是固定的連接池方式,就不適合采取這種算法。例如,LVS可以采取這種算法進(jìn)行負(fù)載均衡,而一個通過連接池的方式連接MySQL集群的負(fù)載均衡系統(tǒng)就不適合采取這種算法進(jìn)行負(fù)載均衡。
? CPU負(fù)載最低優(yōu)先的算法要求負(fù)載均衡系統(tǒng)以某種方式收集每個服務(wù)器的CPU負(fù)載,而且要確定是以1分鐘的負(fù)載為標(biāo)準(zhǔn),還是以15分鐘的負(fù)載為標(biāo)準(zhǔn),不存在1分鐘肯定比15分鐘要好或者差。不同業(yè)務(wù)最優(yōu)的時間間隔是不一樣的,時間間隔太短容易造成頻繁波動,時間間隔太長又可能造成峰值來臨時響應(yīng)緩慢。負(fù)載最低優(yōu)先算法基本上能夠比較完美地解決輪詢算法的缺點,因為采用這種算法后,負(fù)載均衡系統(tǒng)需要感知服務(wù)器當(dāng)前的運行狀態(tài)。當(dāng)然,其代價是復(fù)雜度大幅上升。通俗來講,輪詢可能是5行代碼就能實現(xiàn)的算法,而負(fù)載最低優(yōu)先算法可能要1000行才能實現(xiàn),甚至需要負(fù)載均衡系統(tǒng)和服務(wù)器都要開發(fā)代碼。
Hash類
負(fù)載均衡系統(tǒng)根據(jù)任務(wù)中的某些關(guān)鍵信息進(jìn)行Hash運算,將相同Hash值的請求分配到同一臺服務(wù)器上,這樣做的目的主要是為了滿足特定的業(yè)務(wù)需求。例如:
? 源地址Hash
將來源于同一個源IP地址的任務(wù)分配給同一個服務(wù)器進(jìn)行處理,適合于存在事務(wù)、會話的業(yè)務(wù)。例如,當(dāng)我們通過瀏覽器登錄網(wǎng)上銀行時,會生成一個會話信息,這個會話是臨時的,關(guān)閉瀏覽器后就失效。網(wǎng)上銀行后臺無須持久化會話信息,只需要在某臺服務(wù)器上臨時保存這個會話就可以了,但需要保證用戶在會話存在期間,每次都能訪問到同一個服務(wù)器,這種業(yè)務(wù)場景就可以用源地址Hash來實現(xiàn)。
? ID Hash
將某個ID標(biāo)識的業(yè)務(wù)分配到同一個服務(wù)器中進(jìn)行處理,這里的ID一般是臨時性數(shù)據(jù)的ID(如session id)。例如,上述的網(wǎng)上銀行登錄的例子,用session id hash同樣可以實現(xiàn)同一個會話期間,用戶每次都是訪問到同一臺服務(wù)器的目的。