企业级负载均衡如何实现
轉(zhuǎn)載自??企業(yè)級(jí)負(fù)載均衡如何實(shí)現(xiàn)
負(fù)載均衡簡介
首先,我們來了解一下什么是負(fù)載均衡:
在一個(gè)大型網(wǎng)站中,在線用戶有時(shí)可能有幾千個(gè)甚至上萬個(gè)之多。如果一個(gè)用戶的請(qǐng)求需要服務(wù)使用0.02秒來處理,那么該服務(wù)實(shí)例每秒鐘將只能處理50個(gè)這樣的請(qǐng)求,每分鐘也只能處理3000個(gè)。如果該服務(wù)是一個(gè)用戶非常常用的功能,如瀏覽網(wǎng)站的產(chǎn)品列表,那么很顯然單個(gè)服務(wù)實(shí)例已經(jīng)無法支持該網(wǎng)站的運(yùn)營。在這種情況下,我們就需要對(duì)該服務(wù)進(jìn)行擴(kuò)容。
擴(kuò)容主要分為Scale Up和Scale Out兩種,分別對(duì)應(yīng)著增強(qiáng)單個(gè)服務(wù)的服務(wù)能力以及增強(qiáng)服務(wù)數(shù)量。在某些情況下,Scale Up是一個(gè)較為簡單的操作,例如為該服務(wù)所在的服務(wù)器添加更大的內(nèi)存。但是任意一個(gè)服務(wù)器所能提供的能力實(shí)際上都受到其自身物理硬件能力的限制,尤其是具有越高性能的服務(wù)器其單位服務(wù)能力的價(jià)格越為昂貴,因此我們就需要使用Scale? Out方式將工作量分?jǐn)偟蕉鄠€(gè)服務(wù)器之中:
就如上圖所顯示的那樣,當(dāng)服務(wù)器的負(fù)載過多而來不及處理的時(shí)候,服務(wù)器就處于一種過載的狀態(tài)。在該狀態(tài)的服務(wù)常常會(huì)出現(xiàn)響應(yīng)速度慢甚至無響應(yīng)的情況。而在執(zhí)行了Scale Out之后,我們將會(huì)使用多個(gè)服務(wù)器同時(shí)處理用戶的請(qǐng)求。在該解決方案中,我們需要使用一臺(tái)特定的設(shè)備將這些請(qǐng)求分發(fā)到各個(gè)服務(wù)器。該設(shè)備會(huì)根據(jù)其內(nèi)部所包含的請(qǐng)求分發(fā)邏輯來決定如何對(duì)這些請(qǐng)求進(jìn)行分發(fā),以避免出現(xiàn)單個(gè)服務(wù)器過載的情況。這些用來對(duì)請(qǐng)求進(jìn)行分發(fā)的設(shè)備實(shí)際上就是負(fù)載均衡服務(wù)器。
當(dāng)然,我們不會(huì)等到服務(wù)器真正過載了才去解決這個(gè)問題。在服務(wù)的日常運(yùn)維中,我們?cè)诜?wù)器的平均負(fù)載和峰值負(fù)載達(dá)到某個(gè)特定閾值時(shí)就需要考慮是否需要為相應(yīng)服務(wù)進(jìn)行擴(kuò)容。
一旦一個(gè)服務(wù)使用了負(fù)載均衡系統(tǒng),那么它將在高可用性以及擴(kuò)展性上得到極大的增強(qiáng)。這也是我們使用負(fù)載均衡解決方案的最重要原因。例如對(duì)于一個(gè)擁有三臺(tái)服務(wù)器的負(fù)載均衡系統(tǒng),如果其中一臺(tái)發(fā)生了故障,那么負(fù)載均衡服務(wù)器可以通過向各個(gè)服務(wù)發(fā)送心跳等方式得知它們的異常,進(jìn)而不再向這個(gè)發(fā)生了故障的服務(wù)器分發(fā)任務(wù):
而如果當(dāng)前負(fù)載均衡系統(tǒng)中所負(fù)擔(dān)的服務(wù)容量已經(jīng)超過了閾值,那么我們可以簡單地通過在負(fù)載均衡系統(tǒng)中添加服務(wù)器來解決這個(gè)問題:
這樣,每個(gè)服務(wù)器所需要處理的任務(wù)就相對(duì)減少了,從而減輕了單個(gè)服務(wù)器的負(fù)擔(dān)。
基于DNS的負(fù)載均衡
在了解了負(fù)載均衡系統(tǒng)的大致組成及使用方式之后,我們就來看看各種負(fù)載均衡解決方案。
當(dāng)前企業(yè)中所最常使用的負(fù)載均衡解決方案主要分為三種:基于DNS的負(fù)載均衡,L3/4負(fù)載均衡,也即是基于網(wǎng)絡(luò)層的負(fù)載均衡,以及L7負(fù)載均衡,即基于應(yīng)用層的負(fù)載均衡。在這些解決方案中,基于DNS的負(fù)載均衡是最簡單的,也是最早出現(xiàn)的一種負(fù)載均衡解決方案。
當(dāng)我們通過在瀏覽器的地址欄中鍵入域名來訪問某個(gè)網(wǎng)站時(shí),瀏覽器將首先查找本地的DNS緩存是否擁有該域名所對(duì)應(yīng)的IP地址。如果有,那么瀏覽器將嘗試直接使用該IP地址訪問該網(wǎng)站的內(nèi)容。如果本地DNS緩存中沒有該域名所對(duì)應(yīng)的IP地址,那么它將向DNS發(fā)送一個(gè)請(qǐng)求,以獲得該域名所對(duì)應(yīng)的IP并添加到本地DNS緩存中。
而在DNS中,一個(gè)域名可能和多個(gè)IP地址綁定。在這種情況下,DNS響應(yīng)將會(huì)按照Round Robin方式返回這些IP地址的列表。例如在多次通過nslookup或host等命令來查看特定域名所對(duì)應(yīng)的IP時(shí),其可能的返回如下(因國內(nèi)網(wǎng)絡(luò)原因,您需要FQ再進(jìn)行試驗(yàn)):
$?host?-t?a?google.comgoogle.com?has?address?72.14.207.99google.com?has?address?64.233.167.99google.com?has?address?64.233.187.99$?host?-t?a?google.comgoogle.com?has?address?64.233.187.99google.com?has?address?72.14.207.99google.com?has?address?64.233.167.99可以看到,不同的DNS請(qǐng)求所返回的結(jié)果會(huì)按照Round Robin進(jìn)行輪換,進(jìn)而使得不同的用戶訪問不同的IP地址,平衡各個(gè)服務(wù)器的負(fù)載。
雖然這種負(fù)載均衡解決方案非常容易實(shí)現(xiàn),但是它有一個(gè)致命的缺點(diǎn):為了減少DNS請(qǐng)求的次數(shù)以提高訪問效率,瀏覽器常常緩存了DNS查詢的結(jié)果。如果一個(gè)IP處的服務(wù)失效,那么瀏覽器可能仍會(huì)根據(jù)DNS緩存中所記錄的信息向該不可用的服務(wù)發(fā)送請(qǐng)求(不同的瀏覽器可能有不同的行為)。雖然說整個(gè)服務(wù)只有一處IP所對(duì)應(yīng)的服務(wù)失效了,但是從用戶的角度看來該網(wǎng)站已經(jīng)不可訪問。因此基于DNS的負(fù)載均衡方案并不能作為一個(gè)獨(dú)立的負(fù)載均衡解決方案來提供高可用性的保障,而是作為其它負(fù)載均衡解決方案的補(bǔ)充方案來使用。
L3/4負(fù)載均衡
另一種較為常見的負(fù)載均衡則是L3/4負(fù)載均衡。這里的L3/4實(shí)際上指的就是負(fù)載均衡服務(wù)器會(huì)根據(jù)OSI模型中的第三層網(wǎng)絡(luò)層(Network Layer)和第四層傳輸層(Transport Layer)所包含的數(shù)據(jù)來進(jìn)行負(fù)載均衡操作。在這種負(fù)載均衡服務(wù)器中,這些數(shù)據(jù)主要包含數(shù)據(jù)包的IP頭和TCP、UDP等協(xié)議的協(xié)議頭:
L3/4負(fù)載均衡服務(wù)器的工作原理非常簡單:在數(shù)據(jù)到達(dá)時(shí),負(fù)載均衡服務(wù)器將根據(jù)自身算法以及OSI模型三四層所包含的數(shù)據(jù)決定需要處理該數(shù)據(jù)的服務(wù)實(shí)例并將其轉(zhuǎn)發(fā)。
整個(gè)負(fù)載均衡的運(yùn)行包含三方面內(nèi)容:負(fù)載均衡服務(wù)器需要知道當(dāng)前有效的服務(wù)實(shí)例到底有哪些,并根據(jù)自身的分派算法來決定需要處理數(shù)據(jù)的服務(wù)實(shí)例,根據(jù)分派算法的計(jì)算結(jié)果將數(shù)據(jù)發(fā)送到目標(biāo)服務(wù)實(shí)例上。
首先來看看負(fù)載均衡服務(wù)器是如何確定服務(wù)實(shí)例的有效性的。為了能夠保證從負(fù)載均衡服務(wù)器所派發(fā)的數(shù)據(jù)包能被它后面的服務(wù)器集群正常處理,負(fù)載均衡服務(wù)器需要周期性地發(fā)送狀態(tài)查詢請(qǐng)求以探測(cè)到底哪些服務(wù)實(shí)例正在有效地工作。這種狀態(tài)查詢請(qǐng)求常常會(huì)超出很多人的認(rèn)知:如果服務(wù)實(shí)例崩潰但是承載它的操作系統(tǒng)正常工作,那么該操作系統(tǒng)仍然會(huì)正常響應(yīng)負(fù)載均衡服務(wù)器所發(fā)出的Ping命令,只是此時(shí)TCP連接會(huì)失敗;如果服務(wù)實(shí)例并沒有崩潰,而只是掛起,那么它仍然可以接受TCP連接,只是無法接收HTTP請(qǐng)求。
由于這種狀態(tài)查詢請(qǐng)求實(shí)際上是特定于服務(wù)實(shí)例的具體實(shí)現(xiàn),因此很多負(fù)載均衡服務(wù)器都允許用戶添加自定義腳本以執(zhí)行特定于服務(wù)實(shí)例的查詢。這些狀態(tài)查詢請(qǐng)求常常包含了很多測(cè)試,甚至?xí)L試從服務(wù)實(shí)例中返回?cái)?shù)據(jù)。
一旦負(fù)載均衡服務(wù)器發(fā)現(xiàn)其所管理的某個(gè)服務(wù)實(shí)例不再有效,那么它就不會(huì)再將任何數(shù)據(jù)轉(zhuǎn)發(fā)給該服務(wù)實(shí)例,直到該服務(wù)實(shí)例回歸正常狀態(tài)。在這種情況下,其它各個(gè)服務(wù)實(shí)例就需要分擔(dān)失效服務(wù)器所原本承擔(dān)的工作。
這里需要注意的一點(diǎn)是,在某個(gè)服務(wù)實(shí)例失效以后,整個(gè)系統(tǒng)仍應(yīng)該具有足夠的總?cè)萘恳蕴幚碡?fù)載。舉例來說,假如一個(gè)負(fù)載均衡服務(wù)器管理了三個(gè)具有相同能力的服務(wù)實(shí)例,而且這三個(gè)服務(wù)實(shí)例各自的負(fù)載都在80%左右。如果其中一個(gè)服務(wù)實(shí)例失效,那么所有的負(fù)載都需要由其它兩個(gè)服務(wù)實(shí)例來完成。每個(gè)服務(wù)實(shí)例就需要承擔(dān)120%的負(fù)載,遠(yuǎn)超過了它所具有的負(fù)載能力。這種情況的直接后果就是,服務(wù)顯得非常不穩(wěn)定,并常常有系統(tǒng)超時(shí),應(yīng)用無法正常工作的情況出現(xiàn)。
OK。 現(xiàn)在假設(shè)我們的負(fù)載均衡服務(wù)器有一個(gè)設(shè)計(jì)良好的狀態(tài)查詢請(qǐng)求,那么它就會(huì)根據(jù)其所使用的負(fù)載均衡算法來為工作的服務(wù)實(shí)例分配負(fù)載。對(duì)于初次接觸到負(fù)載均衡功能的人來說,最常見的誤區(qū)就是認(rèn)為負(fù)載均衡服務(wù)器會(huì)根據(jù)各個(gè)服務(wù)實(shí)例的響應(yīng)速度或負(fù)載狀況來決定請(qǐng)求需要到達(dá)的服務(wù)實(shí)例。
通常情況下,Round Robin算法是最常用也是表現(xiàn)最好的負(fù)載均衡算法。如果各個(gè)服務(wù)實(shí)例的容量并不相同,那么負(fù)載均衡服務(wù)器會(huì)使用Weighted Round Robin算法,即根據(jù)各個(gè)服務(wù)實(shí)例的實(shí)際能力來安比例地分配負(fù)載。在某些商業(yè)負(fù)載均衡服務(wù)器中,其的確會(huì)根據(jù)當(dāng)前服務(wù)實(shí)例的負(fù)載以及響應(yīng)時(shí)間等因素對(duì)這些分配比例自動(dòng)進(jìn)行微小地調(diào)整,但是它們并不是決定性的因素。
如果單純地使用Round Robin算法,那么具有關(guān)聯(lián)關(guān)系的各個(gè)請(qǐng)求將可能被分配到不同的服務(wù)實(shí)例上。因此很多負(fù)載均衡服務(wù)器允許根據(jù)數(shù)據(jù)的特定特征對(duì)這些負(fù)載進(jìn)行分配,如使用一種哈希算法來對(duì)用戶所在的IP進(jìn)行計(jì)算,并以計(jì)算結(jié)果決定需要分配到的服務(wù)實(shí)例。
同樣地,我們也需要考慮某個(gè)服務(wù)器實(shí)例失效的情況。如果負(fù)載均衡系統(tǒng)中的某個(gè)服務(wù)器實(shí)例失效,那么哈希算法中的哈希值空間將發(fā)生變化,進(jìn)而導(dǎo)致原本的服務(wù)實(shí)例分配結(jié)果將不再有效。在這種情況下,所有的請(qǐng)求將重新分配服務(wù)器實(shí)例。另外,在某些情況下,用戶的IP也可能在各個(gè)請(qǐng)求之間發(fā)生變化,進(jìn)而導(dǎo)致它所對(duì)應(yīng)的服務(wù)實(shí)例發(fā)生更改。當(dāng)然,不用擔(dān)心,后面對(duì)L7負(fù)載均衡服務(wù)器的講解會(huì)給您一個(gè)解決方案。
在確定了數(shù)據(jù)包的目標(biāo)地址后,負(fù)載均衡服務(wù)器所需要做的事情就是將它們轉(zhuǎn)發(fā)到目標(biāo)實(shí)例了。負(fù)載均衡服務(wù)器所使用的轉(zhuǎn)發(fā)方式主要分為三種:Direct routing,Tunnelling以及IP address translation。
在使用Direct routing方式的時(shí)候,負(fù)載均衡服務(wù)器以及各個(gè)服務(wù)實(shí)例必須在同一個(gè)網(wǎng)段上并使用同一個(gè)IP。在接收到數(shù)據(jù)的時(shí)候,負(fù)載均衡服務(wù)器將直接對(duì)這些數(shù)據(jù)包進(jìn)行轉(zhuǎn)發(fā)。而各個(gè)服務(wù)實(shí)例在處理完數(shù)據(jù)包之后可以將響應(yīng)返回給負(fù)載均衡服務(wù)器,也可以選擇將響應(yīng)直接發(fā)送給用戶,而不需要再經(jīng)過負(fù)載均衡服務(wù)器。后一種返回方式被稱為Direct Server Return。其運(yùn)行方式如下所示:
在該過程中,負(fù)載均衡服務(wù)器和各個(gè)服務(wù)實(shí)例都不需要對(duì)IP(Internet Protocol)層數(shù)據(jù)進(jìn)行任何更改就可以對(duì)其進(jìn)行轉(zhuǎn)發(fā)。使用這種轉(zhuǎn)發(fā)方式的負(fù)載均衡服務(wù)器的吞吐量非常高。反過來,這種組織方式也要求集群的搭建人員對(duì)TCP/IP等協(xié)議擁有足夠多的理解。
另一種轉(zhuǎn)發(fā)方式Tunnelling實(shí)際上與Direct routing類似。唯一的一點(diǎn)不同則是在負(fù)載均衡服務(wù)器和各個(gè)服務(wù)之間建立了一系列通道。軟件開發(fā)人員仍然可以選擇使用Direct Server Return來減輕負(fù)載均衡服務(wù)器的負(fù)載。
IP Address Translation則與前兩種方式非常不同。用戶所連接的目標(biāo)地址實(shí)際上是一個(gè)虛擬地址(VIP,Virtual IP)。而負(fù)載均衡服務(wù)器在接到該請(qǐng)求的時(shí)候?qū)?huì)將其目標(biāo)地址轉(zhuǎn)化為服務(wù)實(shí)例所在的實(shí)際地址(RIP,Real IP),并將源地址更改為Load Balancer所在的地址。這樣在對(duì)請(qǐng)求處理完畢后,服務(wù)實(shí)例將會(huì)把響應(yīng)發(fā)送到負(fù)載均衡服務(wù)器。此時(shí)負(fù)載均衡服務(wù)器再將響應(yīng)的地址更改為VIP,并將該響應(yīng)返回給用戶。在這種轉(zhuǎn)發(fā)方式下,其運(yùn)行流程則如下所示:
有些細(xì)心的讀者會(huì)問:在消息傳遞的過程中,用戶所在的User IP已經(jīng)不在消息中存在了,那負(fù)載均衡服務(wù)器在傳回響應(yīng)的時(shí)候應(yīng)該如何恢復(fù)用戶的IP地址呢?實(shí)際上在這種轉(zhuǎn)發(fā)方式中,負(fù)載均衡服務(wù)器會(huì)維持一系列會(huì)話,以記錄每個(gè)經(jīng)由負(fù)載均衡服務(wù)器的正在處理的各個(gè)請(qǐng)求的相關(guān)信息。但是這些會(huì)話非常危險(xiǎn)。如果將會(huì)話持續(xù)的時(shí)間設(shè)置得比較長,那么在一個(gè)高并發(fā)的負(fù)載均衡服務(wù)器上就需要維護(hù)過多的會(huì)話。反之如果將會(huì)話持續(xù)的時(shí)間設(shè)置得過短,那么就有可能導(dǎo)致ACK Storm發(fā)生。
先看會(huì)話持續(xù)時(shí)間較長的情況。假設(shè)當(dāng)前負(fù)載均衡服務(wù)器每秒鐘會(huì)接收到50000個(gè)請(qǐng)求,而且該負(fù)載均衡服務(wù)器的會(huì)話過期時(shí)間為2分鐘,那么其就需要保持6000000個(gè)會(huì)話。這些會(huì)話會(huì)占用負(fù)載均衡服務(wù)器的很大部分資源。而且在負(fù)載高峰期,其所消耗的資源可能會(huì)成倍地增長,會(huì)向服務(wù)器施加更多的壓力。
但是將會(huì)話持續(xù)時(shí)間設(shè)置得比較短則更為麻煩。這會(huì)導(dǎo)致用戶和負(fù)載均衡服務(wù)器之間產(chǎn)生ACK Storm,占用用戶和負(fù)載均衡服務(wù)器的大量帶寬。在一個(gè)TCP連接中,客戶端和服務(wù)端需要通過各自的Sequence Number來進(jìn)行溝通。如果負(fù)載均衡服務(wù)器上的會(huì)話快速地失效,那么其它TCP連接就有可能重用該會(huì)話。被重用的會(huì)話中客戶端和服務(wù)端的Sequence Number都會(huì)被重新生成。如果此時(shí)原有的用戶再次發(fā)送消息,那么負(fù)載均衡服務(wù)器將通過一個(gè)ACK消息通知客戶端其擁有的Sequence Number出錯(cuò)。而在客戶端接受到該ACK消息之后,其將向負(fù)載均衡服務(wù)器發(fā)送另一個(gè)ACK消息通知服務(wù)端所擁有的Sequence Number出錯(cuò)。服務(wù)端接受到該ACK消息后,將再次發(fā)送ACK消息到客戶端通知其所擁有的Sequence Number出錯(cuò)……這樣客戶端和服務(wù)端之間就將持續(xù)地發(fā)送這種無意義的ACK消息,直到某個(gè)ACK消息在網(wǎng)絡(luò)傳輸過程中丟失為止。
因此乍一看來,使用IP Address Translation的方案是最容易的,但是相較于其它兩種方案,它卻是最危險(xiǎn)也是維護(hù)成本最高的一種方案。
L7負(fù)載均衡
另一種較為常用的負(fù)載均衡解決方案則是L7負(fù)載均衡。顧名思義,其主要通過OSI模型中的第七層應(yīng)用層中的數(shù)據(jù)決定如何分發(fā)負(fù)載。
在運(yùn)行時(shí),L7負(fù)載均衡服務(wù)器上的操作系統(tǒng)會(huì)將接收到的各個(gè)數(shù)據(jù)包組織成為用戶請(qǐng)求,并根據(jù)在該請(qǐng)求中所包含的的數(shù)據(jù)來決定由哪個(gè)服務(wù)實(shí)例來對(duì)該請(qǐng)求進(jìn)行處理。其運(yùn)行流程圖大致如下所示:
相較于L3/4負(fù)載均衡服務(wù)所使用的數(shù)據(jù),L7負(fù)載均衡服務(wù)所使用的應(yīng)用層數(shù)據(jù)更貼近服務(wù)本身,因此其具有更精確的負(fù)載均衡行為。
在前面對(duì)L3/4負(fù)載均衡的講解中我們已經(jīng)介紹過,對(duì)于某些具有關(guān)聯(lián)關(guān)系的各個(gè)請(qǐng)求,L3/4負(fù)載均衡服務(wù)器會(huì)根據(jù)某些算法(如計(jì)算IP的哈希值)來決定處理該請(qǐng)求的服務(wù)實(shí)例。但是這種方法并不是很穩(wěn)定。當(dāng)一個(gè)服務(wù)實(shí)例失效或用戶的IP發(fā)生變化的時(shí)候,用戶與服務(wù)實(shí)例之間的對(duì)應(yīng)關(guān)系就將發(fā)生改變。此時(shí)用戶原有的會(huì)話數(shù)據(jù)在新的服務(wù)實(shí)例上并不存在,進(jìn)而導(dǎo)致一系列問題。
其實(shí)產(chǎn)生這個(gè)問題的最根本原因就是用戶與服務(wù)實(shí)例之間的關(guān)聯(lián)關(guān)系是通過某些外部環(huán)境創(chuàng)建的,而并非由用戶/服務(wù)實(shí)例本身來管理。因此它不能抵御外部環(huán)境變化的沖擊。如果要在用戶和服務(wù)實(shí)例之間建立穩(wěn)定的關(guān)聯(lián)關(guān)系,那么就需要一種穩(wěn)定的在用戶和服務(wù)實(shí)例之間傳遞的數(shù)據(jù)。在Web服務(wù)中,這種數(shù)據(jù)就是Cookie。
簡單地說,基于Cookie的負(fù)載均衡服務(wù)實(shí)際上就是分析用戶請(qǐng)求中的某個(gè)特定Cookie并根據(jù)其值決定需要分發(fā)到的目標(biāo)地址。其主要分為兩種方式:Cookie? Learning以及Cookie Insertion。
Cookie Learning是不具有侵入性的一種解決方案。其通過分析用戶與服務(wù)實(shí)例通訊過程中所傳遞的Cookie來決定如何分派負(fù)載:在用戶與服務(wù)第一次通訊時(shí),負(fù)載均衡服務(wù)將找不到相應(yīng)的Cookie,因此其將會(huì)把該請(qǐng)求根據(jù)負(fù)載均衡算法分配到某個(gè)服務(wù)實(shí)例上。而在服務(wù)實(shí)例返回的時(shí)候,負(fù)載均衡服務(wù)器將會(huì)把對(duì)應(yīng)的Cookie以及服務(wù)實(shí)例的地址記錄在負(fù)載均衡服務(wù)器中。當(dāng)用戶再次與服務(wù)通訊時(shí),負(fù)載均衡服務(wù)器就會(huì)根據(jù)Cookie中所記錄的數(shù)據(jù)找到前一次服務(wù)該用戶的服務(wù)實(shí)例,并將請(qǐng)求轉(zhuǎn)發(fā)到該服務(wù)實(shí)例上。
這么做的最大缺點(diǎn)就是對(duì)高可用性的支持很差。如果一旦負(fù)載均衡服務(wù)器失效,那么在該負(fù)載均衡服務(wù)器上所維護(hù)的Cookie和服務(wù)實(shí)例之間的匹配關(guān)系將全部丟失。這樣當(dāng)備份負(fù)載均衡服務(wù)器啟動(dòng)之后,所有的用戶請(qǐng)求都將被定向到隨機(jī)的服務(wù)實(shí)例。
而另一個(gè)問題就是會(huì)話維護(hù)功能對(duì)內(nèi)存的消耗。與L3/4服務(wù)器上的會(huì)話維護(hù)不同,一個(gè)Cookie的失效時(shí)間可能非常長,至少在一次用戶使用中可能會(huì)持續(xù)幾個(gè)小時(shí)。對(duì)于一個(gè)訪問量達(dá)到每秒上萬次的系統(tǒng)而言,負(fù)載均衡服務(wù)器需要維護(hù)非常多的會(huì)話,甚至可能會(huì)將服務(wù)器的內(nèi)存消耗殆盡。反過來,如果將負(fù)載均衡服務(wù)器中的Cookie過期時(shí)間設(shè)置得太短,那么當(dāng)用戶重新訪問負(fù)載均衡服務(wù)器的時(shí)候,其將被導(dǎo)向到一個(gè)錯(cuò)誤的服務(wù)實(shí)例。
除了Cookie Learning 之外,另一種常用的方法就是Cookie Insertion。其通過向響應(yīng)中添加Cookie以記錄被分派到的服務(wù)實(shí)例,并在下一次處理請(qǐng)求時(shí)根據(jù)該Cookie所保存的值來決定分發(fā)到的服務(wù)實(shí)例。在用戶與服務(wù)器進(jìn)行第一次通訊的時(shí)候,負(fù)載均衡服務(wù)器將找不到分派記錄所對(duì)應(yīng)的Cookie,因此其會(huì)根據(jù)負(fù)載均衡算法為該請(qǐng)求分配一個(gè)服務(wù)實(shí)例。在接收到服務(wù)實(shí)例所返回的數(shù)據(jù)之后,負(fù)載均衡服務(wù)器將會(huì)向響應(yīng)中插入一個(gè)Cookie,以記錄該服務(wù)實(shí)例的ID。當(dāng)用戶再次發(fā)送請(qǐng)求到負(fù)載均衡服務(wù)器時(shí),其將根據(jù)該Cookie里所記錄的服務(wù)實(shí)例的ID派發(fā)該請(qǐng)求。
相較于Cookie Learning,Cookie Insertion不需要在內(nèi)存中維護(hù)Cookie與各個(gè)服務(wù)實(shí)例的對(duì)應(yīng)關(guān)系,而且在當(dāng)前負(fù)載均衡服務(wù)器失效的時(shí)候,備用負(fù)載均衡服務(wù)器也可以根據(jù)Cookie中所記錄的信息正確地派發(fā)各個(gè)請(qǐng)求。
當(dāng)然,Cookie Insertion也有缺陷。最常見的問題就是瀏覽器以及用戶自身對(duì)Cookie的限制。在Cookie Insertion中,我們需要插入一個(gè)額外的Cookie 來記錄分配給當(dāng)前用戶的服務(wù)實(shí)例。但是在某些瀏覽器中,特別是移動(dòng)瀏覽器中,常常會(huì)限制Cookie的個(gè)數(shù),甚至只允許出現(xiàn)一個(gè) Cookie。為了解決這個(gè)問題,負(fù)載均衡服務(wù)器也會(huì)使用一些其它方法。如Cookie Modification,即修改一個(gè)已有的Cookie使其包含服務(wù)實(shí)例的ID。
而在用戶禁用了Cookie的時(shí)候,Cookie Insertion將是完全失效的。此時(shí)負(fù)載均衡服務(wù)所能利用的將僅僅是JSESSIONID等信息。因此在一個(gè)L7負(fù)載均衡服務(wù)器中,Cookie Learning和Cookie Insertion常常同時(shí)使用:Cookie Learning會(huì)在用戶啟用Cookie的時(shí)候起主要作用,而在Cookie被用戶禁用的情況下則使用Cookie Learning來根據(jù)JSESSIONID來保持用戶與服務(wù)實(shí)例之間的關(guān)聯(lián)關(guān)系。
或許你會(huì)想:L3/4負(fù)載均衡服務(wù)器在處理各個(gè)關(guān)聯(lián)請(qǐng)求的時(shí)候是通過IP的哈希值來決定處理該請(qǐng)求的服務(wù)實(shí)例的。既然這些基于Cookie的解決方案能達(dá)到100%的準(zhǔn)確,為什么我們不在L3/4負(fù)載均衡服務(wù)器中使用它們呢?答案是:由于L3/4負(fù)載均衡服務(wù)器主要關(guān)注于數(shù)據(jù)包級(jí)別的轉(zhuǎn)發(fā),而Cookie信息則藏匿于數(shù)據(jù)包之中,因此L3/4負(fù)載均衡服務(wù)器很難決定單一的數(shù)據(jù)包該如何轉(zhuǎn)發(fā)。
例如在執(zhí)行Cookie Insertion操作的時(shí)候,原有數(shù)據(jù)包中的所有數(shù)據(jù)都將被后移。此時(shí)需要負(fù)載均衡服務(wù)器接收到所有數(shù)據(jù)包之后才能完成:
試想一下接收所有數(shù)據(jù)包所可能發(fā)生的事情吧。在網(wǎng)絡(luò)的一端發(fā)送多個(gè)數(shù)據(jù)包的時(shí)候,網(wǎng)絡(luò)的另一端所接收到的數(shù)據(jù)包的順序可能與原有的發(fā)送順序并不一致。甚至在網(wǎng)絡(luò)擁堵的時(shí)候,某些數(shù)據(jù)包可能會(huì)丟失,進(jìn)而再次加長接收到所有數(shù)據(jù)包所需要的時(shí)間。
因此相較于將數(shù)據(jù)包直接轉(zhuǎn)發(fā)的方法,等待所有的數(shù)據(jù)包到齊然后再插入Cookie的性能非常差。在后面對(duì)于解決方案的講解中您會(huì)看到,L3/4負(fù)載均衡服務(wù)器對(duì)于性能的要求一般來說是很高的,而L7負(fù)載均衡服務(wù)器則可以通過一個(gè)集群來解決自身的性能問題。基于DNS的負(fù)載均衡,L3/4負(fù)載均衡服務(wù)器以及L7負(fù)載均衡服務(wù)器常常協(xié)同工作,以組成一個(gè)具有高可用性以及高可擴(kuò)展性的系統(tǒng)。
SSL Farm
在上面的講解中,我們忽略了一個(gè)事情,那就是L7負(fù)載均衡服務(wù)器對(duì)于SSL的支持。在L7負(fù)載均衡服務(wù)器中,我們常常需要讀寫請(qǐng)求及響應(yīng)中的Cookie。但是如果通訊使用的是SSL連接,那么L7負(fù)載均衡服務(wù)器將無法對(duì)請(qǐng)求及響應(yīng)的內(nèi)容進(jìn)行讀寫操作。
解決該問題所曾經(jīng)使用的一個(gè)解決方案就是:將負(fù)載均衡服務(wù)器以反向代理的方式使用。在這種方案中,負(fù)載均衡服務(wù)器將擁有服務(wù)的證書,并可以通過證書中的密鑰對(duì)請(qǐng)求進(jìn)行解密。解密完成后,負(fù)載均衡服務(wù)器就可以開始嘗試讀取Cookie中的內(nèi)容并根據(jù)其所記錄的信息決定該請(qǐng)求所需要派發(fā)到的服務(wù)實(shí)例。在對(duì)該請(qǐng)求進(jìn)行派發(fā)的時(shí)候,負(fù)載均衡服務(wù)器可以不再使用SSL連接,進(jìn)而使得各個(gè)服務(wù)實(shí)例不再需要再次解密請(qǐng)求,提高服務(wù)實(shí)例的運(yùn)行效率。
在請(qǐng)求處理完畢之后,服務(wù)實(shí)例將通過服務(wù)實(shí)例與負(fù)載均衡服務(wù)器的非SSL連接返回一個(gè)響應(yīng)。在負(fù)載均衡服務(wù)器接收到該響應(yīng)之后,其將會(huì)把該響應(yīng)加密并通過SSL連接發(fā)出:
但是這樣做的問題在于,如果所有對(duì)SSL的處理都集中在L7負(fù)載均衡服務(wù)器上,那么它將會(huì)變成系統(tǒng)的瓶頸。繞過該問題的方法就是在L7負(fù)載均衡服務(wù)器之前使用一系列反向代理來負(fù)責(zé)SSL的編解碼操作。
此時(shí)整個(gè)系統(tǒng)的架構(gòu)將呈現(xiàn)如下的層次結(jié)構(gòu):
從上圖中可以看到,整個(gè)解決方案分為了四層。在用戶的請(qǐng)求到達(dá)了第一層的負(fù)載均衡服務(wù)器時(shí),其將會(huì)把該請(qǐng)求根據(jù)自身的負(fù)載均衡算法轉(zhuǎn)發(fā)給處于第二層的專門負(fù)責(zé)SSL編解碼工作的反向代理。該代理會(huì)將傳入的由SSL連接所傳輸?shù)恼?qǐng)求由非SSL連接傳出。在請(qǐng)求到達(dá)第三層時(shí),L7負(fù)載均衡服務(wù)器可以直接訪問這些請(qǐng)求所包含的Cookie,并根據(jù)Cookie中的內(nèi)容決定需要處理該請(qǐng)求的服務(wù)實(shí)例。
這么做的好處有很多。首先就是這些反向代理非常便宜,甚至只有常見負(fù)載均衡服務(wù)器的1/20左右的價(jià)格,卻在處理SSL連接上擁有幾乎相同的效率。除此之外,這些反向代理還提供了非常良好的擴(kuò)展性和高可用性。一旦負(fù)載均衡系統(tǒng)在處理SSL連接的能力上顯得有些吃力,我們就隨時(shí)可以向系統(tǒng)中添加新的反向代理。而一旦其中一個(gè)反向代理失效,那么其它反向代理可以通過多承擔(dān)一些負(fù)載來保證系統(tǒng)的安全運(yùn)行。
需要考慮的問題
在提出具體的負(fù)載均衡解決方案之前,我們需要首先講解一下在設(shè)計(jì)負(fù)載均衡系統(tǒng)時(shí)我們所需要考慮的一些事情。
首先要說的就是要在負(fù)載均衡系統(tǒng)設(shè)計(jì)時(shí)留意它的高可用性及擴(kuò)展性。在一開始的講解中,我們就已經(jīng)提到過通過使用負(fù)載均衡,由眾多服務(wù)器實(shí)例所組成的服務(wù)具有很高的可用性及擴(kuò)展性。當(dāng)其中一個(gè)服務(wù)實(shí)例失效的時(shí)候,其它服務(wù)實(shí)例可以幫助它分擔(dān)一部分工作。而在總服務(wù)容量顯得有些緊張的時(shí)候,我們可以向服務(wù)中添加新的服務(wù)實(shí)例以擴(kuò)展服務(wù)的總?cè)萘俊?/p>
但是由于所有的數(shù)據(jù)傳輸都需要經(jīng)過負(fù)載均衡服務(wù)器,因此負(fù)載均衡服務(wù)器一旦失效,那么整個(gè)系統(tǒng)就將無法使用。也就是說,負(fù)載均衡服務(wù)器的可用性影響著整個(gè)系統(tǒng)的高可用性。
解決這個(gè)問題的方法要根據(jù)負(fù)載均衡服務(wù)器的類型來討論。對(duì)于L3/4負(fù)載均衡服務(wù)器而言,為了能夠讓整個(gè)系統(tǒng)不失效,業(yè)界中的常用方法是在系統(tǒng)中使用一對(duì)負(fù)載均衡服務(wù)器。當(dāng)其中一個(gè)負(fù)載均衡服務(wù)器失效的時(shí)候,另一個(gè)還能夠?yàn)檎麄€(gè)系統(tǒng)提供負(fù)載均衡服務(wù)。這一對(duì)負(fù)載均衡服務(wù)器可以按照Active-Passive模式使用,也可以按照Active-Active模式使用。
在Active-Passive模式中,一個(gè)負(fù)載均衡服務(wù)器處于半休眠狀態(tài)。其將會(huì)通過向另外一個(gè)負(fù)載均衡服務(wù)器發(fā)送心跳消息來探測(cè)對(duì)方的可用性。當(dāng)正在工作的負(fù)載均衡服務(wù)器不再響應(yīng)心跳的時(shí)候,那么心跳應(yīng)用將會(huì)把負(fù)載均衡服務(wù)器從半休眠狀態(tài)喚醒,接管負(fù)載均衡服務(wù)器的IP并開始執(zhí)行負(fù)載均衡功能。
而在Active-Active模式中,兩臺(tái)負(fù)載均衡服務(wù)器會(huì)同時(shí)工作。如果其中一臺(tái)服務(wù)器發(fā)生了故障,那么另一臺(tái)服務(wù)器將會(huì)承擔(dān)所有的工作:
可以說,兩者各有千秋。相較而言,Active-Active模式具有較好的抵抗訪問量大幅波動(dòng)的情況。例如在通常情況下,兩個(gè)服務(wù)器的負(fù)載都在30%左右,但是在服務(wù)使用的高峰時(shí)間,訪問量可能是平時(shí)的兩倍,因此兩個(gè)服務(wù)器的負(fù)載就將達(dá)到60%左右,仍處于系統(tǒng)可以處理的范圍內(nèi)。如果我們使用的是Active-Passive模式,那么平時(shí)的負(fù)載就將達(dá)到60%,而在高峰時(shí)間的負(fù)載將達(dá)到負(fù)載均衡服務(wù)器容量的120%,進(jìn)而使得服務(wù)無法處理所有的用戶請(qǐng)求。
反過來,Active-Active模式也有不好的地方,那就是容易導(dǎo)致管理上的疏忽。例如在一個(gè)使用了Active-Active模式的系統(tǒng)中,兩個(gè)負(fù)載均衡服務(wù)器的負(fù)載常年都在60%左右。那么一旦其中的一個(gè)負(fù)載均衡服務(wù)器失效了,那么剩下的唯一一個(gè)服務(wù)器同樣將無法處理所有的用戶請(qǐng)求。
或許你會(huì)問:L3/4負(fù)載均衡服務(wù)器一定要有兩個(gè)么?其實(shí)主要由各負(fù)載均衡服務(wù)器產(chǎn)品自身來決定的。在前面我們已經(jīng)講過,實(shí)際上探測(cè)負(fù)載均衡服務(wù)器的可用性實(shí)際上需要很復(fù)雜的測(cè)試邏輯。因此如果一旦我們?cè)谝粋€(gè)負(fù)載均衡系統(tǒng)中使用了過多的L3/4負(fù)載均衡服務(wù)器,那么這些負(fù)載均衡服務(wù)器之間所發(fā)送的各種心跳測(cè)試將消耗非常多的資源。同時(shí)由于很多L3/4負(fù)載均衡服務(wù)器本身是基于硬件的,因此它能夠非常快速地工作,甚至可以達(dá)到與其所支持的網(wǎng)絡(luò)帶寬所匹配的處理能力。因此在一般情況下,L3/4負(fù)載均衡服務(wù)器是成對(duì)使用的。
如果L3/4負(fù)載均衡服務(wù)器真的接近其負(fù)載極限,那么我們還可以通過DNS負(fù)載均衡來分散請(qǐng)求:
這種方法不僅僅可以解決擴(kuò)展性的問題,更可以利用DNS的一個(gè)特性來提高用戶體驗(yàn):DNS可以根據(jù)用戶所在的區(qū)域選擇距離用戶最近的服務(wù)器。這在一個(gè)全球性的服務(wù)中尤為有效。畢竟一個(gè)中國用戶訪問在中國架設(shè)的服務(wù)實(shí)例要比訪問在美國架設(shè)的服務(wù)實(shí)例快得多。
反過來由于L7負(fù)載均衡服務(wù)器主要是基于軟件的,因此很多L7負(fù)載均衡服務(wù)器允許用戶創(chuàng)建較為復(fù)雜的負(fù)載均衡服務(wù)器系統(tǒng)。例如定義一個(gè)具有兩個(gè)啟用而有一個(gè)備用的一組L7負(fù)載均衡服務(wù)器。
講解完了高可用性,我們就來介紹一下負(fù)載均衡服務(wù)器的擴(kuò)展性。其實(shí)在上面我們剛剛介紹過,L3/4負(fù)載均衡服務(wù)器擁有很高的性能,因此一般的服務(wù)所使用的負(fù)載均衡系統(tǒng)不會(huì)遇到需要擴(kuò)展性的問題。但是一旦出現(xiàn)了需要擴(kuò)展的情況,那么使用DNS負(fù)載均衡就可以達(dá)到較好的擴(kuò)展性。而L7負(fù)載均衡則更為靈活,因此擴(kuò)展性更不是問題。
但是一個(gè)負(fù)載均衡系統(tǒng)不可能都是由L3/4負(fù)載均衡服務(wù)器組成的,也不可能只由L7負(fù)載均衡服務(wù)器組成的。這是因?yàn)閮烧咴谛阅芎蛢r(jià)格上都具有非常大的差異。一個(gè)L3/4負(fù)載均衡服務(wù)器實(shí)際上價(jià)格非常昂貴,常常達(dá)到上萬美元。而L7負(fù)載均衡服務(wù)器則可以使用廉價(jià)服務(wù)器搭建。L3/4負(fù)載均衡服務(wù)器常常具有非常高的性能,而L7負(fù)載均衡服務(wù)器則常常通過組成一個(gè)集群來達(dá)到較高的整體性能。
在設(shè)計(jì)負(fù)載均衡系統(tǒng)時(shí),還有一點(diǎn)需要考慮的那就是服務(wù)的動(dòng)靜分離。我們知道,一個(gè)服務(wù)常常由動(dòng)態(tài)請(qǐng)求和靜態(tài)請(qǐng)求共同組成。這兩種請(qǐng)求具有非常不同的特點(diǎn):一個(gè)動(dòng)態(tài)請(qǐng)求常常需要大量的計(jì)算而傳輸?shù)臄?shù)據(jù)常常不是很多,而一個(gè)靜態(tài)的請(qǐng)求常常需要傳輸大量的數(shù)據(jù)而不需要太多的計(jì)算。不同的服務(wù)容器對(duì)這些請(qǐng)求的表現(xiàn)差異很大。因此很多服務(wù)常常將其所包含的服務(wù)實(shí)例分為兩部分,分別用來處理靜態(tài)請(qǐng)求和動(dòng)態(tài)請(qǐng)求,并使用適合的服務(wù)容器提供服務(wù)。在這種情況下,靜態(tài)請(qǐng)求常常被置于特定的路徑下,如“/static”。這樣負(fù)載均衡服務(wù)器就可以根據(jù)請(qǐng)求所發(fā)送到的路徑而將動(dòng)態(tài)請(qǐng)求和靜態(tài)請(qǐng)求進(jìn)行適當(dāng)?shù)剞D(zhuǎn)發(fā)。
最后要提到的就是L3/4負(fù)載均衡服務(wù)器的一個(gè)軟件實(shí)現(xiàn)LVS(Linux Virtual Server)。相較于硬件實(shí)現(xiàn),軟件實(shí)現(xiàn)需要做很多額外的工作,例如對(duì)數(shù)據(jù)包的解碼,為處理數(shù)據(jù)包分配內(nèi)存等等呢個(gè)。因此其性能常常只是具有相同硬件能力的L3/4負(fù)載均衡服務(wù)器的1/5到1/10。鑒于其只具有有限的性能但是搭建起來成本很低,如利用已有的在Lab里閑置的機(jī)器等,因此其常常在服務(wù)規(guī)模不是很大的時(shí)候作為臨時(shí)替代方案使用。
負(fù)載均衡解決方案
在文章的最后,我們將給出一系列常見的負(fù)載均衡解決方案,以供大家參考。
在一般情況下,一個(gè)服務(wù)的負(fù)載常常是通過某些方式逐漸增長的。相應(yīng)地,這些服務(wù)所擁有的負(fù)載均衡系統(tǒng)常常是從小到大逐漸演化的。因此我們也將會(huì)按照從小到大的方式逐次介紹這些負(fù)載均衡系統(tǒng)。
首先是最簡單的包含一對(duì)L7負(fù)載均衡服務(wù)器的系統(tǒng):
如果服務(wù)的負(fù)載逐漸增大,那么該系統(tǒng)中唯一的L7負(fù)載均衡服務(wù)器很容易變成瓶頸。此時(shí)我們可以通過添加一個(gè)SSL Farm以及運(yùn)行LVS的服務(wù)器來解決問題:
如果我們還要應(yīng)對(duì)增長的負(fù)載,那么就需要使用真正的基于硬件的L3/4負(fù)載均衡服務(wù)器來替代LVS,并增加各層的容量:
由于該解決方案的下面三層基本都有理論上無限的擴(kuò)展性,因此最容易出現(xiàn)過載的就是最上面的L3/4負(fù)載均衡服務(wù)器。在這種情況下,我們就需要使用DNS來分配負(fù)載了:
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的企业级负载均衡如何实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 抖音设置密友是什么意思
- 下一篇: 手机照片怎么制作背景