小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

企業(yè)級負(fù)載均衡如何實(shí)現(xiàn)

 萬皇之皇 2018-07-31

來自:

www.cnblogs.com/loveis715/p/4547968.html


負(fù)載均衡簡介

首先,我們來了解一下什么是負(fù)載均衡:

在一個大型網(wǎng)站中,在線用戶有時可能有幾千個甚至上萬個之多。如果一個用戶的請求需要服務(wù)使用0.02秒來處理,那么該服務(wù)實(shí)例每秒鐘將只能處理50個這樣的請求,每分鐘也只能處理3000個。如果該服務(wù)是一個用戶非常常用的功能,如瀏覽網(wǎng)站的產(chǎn)品列表,那么很顯然單個服務(wù)實(shí)例已經(jīng)無法支持該網(wǎng)站的運(yùn)營。在這種情況下,我們就需要對該服務(wù)進(jìn)行擴(kuò)容。

擴(kuò)容主要分為Scale Up和Scale Out兩種,分別對應(yīng)著增強(qiáng)單個服務(wù)的服務(wù)能力以及增強(qiáng)服務(wù)數(shù)量。在某些情況下,Scale Up是一個較為簡單的操作,例如為該服務(wù)所在的服務(wù)器添加更大的內(nèi)存。但是任意一個服務(wù)器所能提供的能力實(shí)際上都受到其自身物理硬件能力的限制,尤其是具有越高性能的服務(wù)器其單位服務(wù)能力的價格越為昂貴,因此我們就需要使用Scale  Out方式將工作量分?jǐn)偟蕉鄠€服務(wù)器之中:

就如上圖所顯示的那樣,當(dāng)服務(wù)器的負(fù)載過多而來不及處理的時候,服務(wù)器就處于一種過載的狀態(tài)。在該狀態(tài)的服務(wù)常常會出現(xiàn)響應(yīng)速度慢甚至無響應(yīng)的情況。而在執(zhí)行了Scale Out之后,我們將會使用多個服務(wù)器同時處理用戶的請求。在該解決方案中,我們需要使用一臺特定的設(shè)備將這些請求分發(fā)到各個服務(wù)器。該設(shè)備會根據(jù)其內(nèi)部所包含的請求分發(fā)邏輯來決定如何對這些請求進(jìn)行分發(fā),以避免出現(xiàn)單個服務(wù)器過載的情況。這些用來對請求進(jìn)行分發(fā)的設(shè)備實(shí)際上就是負(fù)載均衡服務(wù)器。

當(dāng)然,我們不會等到服務(wù)器真正過載了才去解決這個問題。在服務(wù)的日常運(yùn)維中,我們在服務(wù)器的平均負(fù)載和峰值負(fù)載達(dá)到某個特定閾值時就需要考慮是否需要為相應(yīng)服務(wù)進(jìn)行擴(kuò)容。

一旦一個服務(wù)使用了負(fù)載均衡系統(tǒng),那么它將在高可用性以及擴(kuò)展性上得到極大的增強(qiáng)。這也是我們使用負(fù)載均衡解決方案的最重要原因。例如對于一個擁有三臺服務(wù)器的負(fù)載均衡系統(tǒng),如果其中一臺發(fā)生了故障,那么負(fù)載均衡服務(wù)器可以通過向各個服務(wù)發(fā)送心跳等方式得知它們的異常,進(jìn)而不再向這個發(fā)生了故障的服務(wù)器分發(fā)任務(wù):

而如果當(dāng)前負(fù)載均衡系統(tǒng)中所負(fù)擔(dān)的服務(wù)容量已經(jīng)超過了閾值,那么我們可以簡單地通過在負(fù)載均衡系統(tǒng)中添加服務(wù)器來解決這個問題:

這樣,每個服務(wù)器所需要處理的任務(wù)就相對減少了,從而減輕了單個服務(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)我們通過在瀏覽器的地址欄中鍵入域名來訪問某個網(wǎng)站時,瀏覽器將首先查找本地的DNS緩存是否擁有該域名所對應(yīng)的IP地址。如果有,那么瀏覽器將嘗試直接使用該IP地址訪問該網(wǎng)站的內(nèi)容。如果本地DNS緩存中沒有該域名所對應(yīng)的IP地址,那么它將向DNS發(fā)送一個請求,以獲得該域名所對應(yīng)的IP并添加到本地DNS緩存中。

而在DNS中,一個域名可能和多個IP地址綁定。在這種情況下,DNS響應(yīng)將會按照Round Robin方式返回這些IP地址的列表。例如在多次通過nslookup或host等命令來查看特定域名所對應(yīng)的IP時,其可能的返回如下(因國內(nèi)網(wǎng)絡(luò)原因,您需要FQ再進(jìn)行試驗(yàn)):

  $ host -t a google.com  google.com has address 72.14.207.99  google.com has address 64.233.167.99  google.com has address 64.233.187.99

  $ host -t a google.com  google.com has address 64.233.187.99  google.com has address 72.14.207.99  google.com has address 64.233.167.99

可以看到,不同的DNS請求所返回的結(jié)果會按照Round Robin進(jìn)行輪換,進(jìn)而使得不同的用戶訪問不同的IP地址,平衡各個服務(wù)器的負(fù)載。

雖然這種負(fù)載均衡解決方案非常容易實(shí)現(xiàn),但是它有一個致命的缺點(diǎn):為了減少DNS請求的次數(shù)以提高訪問效率,瀏覽器常常緩存了DNS查詢的結(jié)果。如果一個IP處的服務(wù)失效,那么瀏覽器可能仍會根據(jù)DNS緩存中所記錄的信息向該不可用的服務(wù)發(fā)送請求(不同的瀏覽器可能有不同的行為)。雖然說整個服務(wù)只有一處IP所對應(yīng)的服務(wù)失效了,但是從用戶的角度看來該網(wǎng)站已經(jīng)不可訪問。因此基于DNS的負(fù)載均衡方案并不能作為一個獨(dú)立的負(fù)載均衡解決方案來提供高可用性的保障,而是作為其它負(fù)載均衡解決方案的補(bǔ)充方案來使用。

L3/4負(fù)載均衡

另一種較為常見的負(fù)載均衡則是L3/4負(fù)載均衡。這里的L3/4實(shí)際上指的就是負(fù)載均衡服務(wù)器會根據(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á)時,負(fù)載均衡服務(wù)器將根據(jù)自身算法以及OSI模型三四層所包含的數(shù)據(jù)決定需要處理該數(shù)據(jù)的服務(wù)實(shí)例并將其轉(zhuǎn)發(fā)。

整個負(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)查詢請求以探測到底哪些服務(wù)實(shí)例正在有效地工作。這種狀態(tài)查詢請求常常會超出很多人的認(rèn)知:如果服務(wù)實(shí)例崩潰但是承載它的操作系統(tǒng)正常工作,那么該操作系統(tǒng)仍然會正常響應(yīng)負(fù)載均衡服務(wù)器所發(fā)出的Ping命令,只是此時TCP連接會失??;如果服務(wù)實(shí)例并沒有崩潰,而只是掛起,那么它仍然可以接受TCP連接,只是無法接收HTTP請求。

由于這種狀態(tài)查詢請求實(shí)際上是特定于服務(wù)實(shí)例的具體實(shí)現(xiàn),因此很多負(fù)載均衡服務(wù)器都允許用戶添加自定義腳本以執(zhí)行特定于服務(wù)實(shí)例的查詢。這些狀態(tài)查詢請求常常包含了很多測試,甚至?xí)L試從服務(wù)實(shí)例中返回數(shù)據(jù)。

一旦負(fù)載均衡服務(wù)器發(fā)現(xiàn)其所管理的某個服務(wù)實(shí)例不再有效,那么它就不會再將任何數(shù)據(jù)轉(zhuǎn)發(fā)給該服務(wù)實(shí)例,直到該服務(wù)實(shí)例回歸正常狀態(tài)。在這種情況下,其它各個服務(wù)實(shí)例就需要分擔(dān)失效服務(wù)器所原本承擔(dān)的工作。

這里需要注意的一點(diǎn)是,在某個服務(wù)實(shí)例失效以后,整個系統(tǒng)仍應(yīng)該具有足夠的總?cè)萘恳蕴幚碡?fù)載。舉例來說,假如一個負(fù)載均衡服務(wù)器管理了三個具有相同能力的服務(wù)實(shí)例,而且這三個服務(wù)實(shí)例各自的負(fù)載都在80%左右。如果其中一個服務(wù)實(shí)例失效,那么所有的負(fù)載都需要由其它兩個服務(wù)實(shí)例來完成。每個服務(wù)實(shí)例就需要承擔(dān)120%的負(fù)載,遠(yuǎn)超過了它所具有的負(fù)載能力。這種情況的直接后果就是,服務(wù)顯得非常不穩(wěn)定,并常常有系統(tǒng)超時,應(yīng)用無法正常工作的情況出現(xiàn)。

OK。 現(xiàn)在假設(shè)我們的負(fù)載均衡服務(wù)器有一個設(shè)計(jì)良好的狀態(tài)查詢請求,那么它就會根據(jù)其所使用的負(fù)載均衡算法來為工作的服務(wù)實(shí)例分配負(fù)載。對于初次接觸到負(fù)載均衡功能的人來說,最常見的誤區(qū)就是認(rèn)為負(fù)載均衡服務(wù)器會根據(jù)各個服務(wù)實(shí)例的響應(yīng)速度或負(fù)載狀況來決定請求需要到達(dá)的服務(wù)實(shí)例。

通常情況下,Round Robin算法是最常用也是表現(xiàn)最好的負(fù)載均衡算法。如果各個服務(wù)實(shí)例的容量并不相同,那么負(fù)載均衡服務(wù)器會使用Weighted Round Robin算法,即根據(jù)各個服務(wù)實(shí)例的實(shí)際能力來安比例地分配負(fù)載。在某些商業(yè)負(fù)載均衡服務(wù)器中,其的確會根據(jù)當(dāng)前服務(wù)實(shí)例的負(fù)載以及響應(yīng)時間等因素對這些分配比例自動進(jìn)行微小地調(diào)整,但是它們并不是決定性的因素。

如果單純地使用Round Robin算法,那么具有關(guān)聯(lián)關(guān)系的各個請求將可能被分配到不同的服務(wù)實(shí)例上。因此很多負(fù)載均衡服務(wù)器允許根據(jù)數(shù)據(jù)的特定特征對這些負(fù)載進(jìn)行分配,如使用一種哈希算法來對用戶所在的IP進(jìn)行計(jì)算,并以計(jì)算結(jié)果決定需要分配到的服務(wù)實(shí)例。

同樣地,我們也需要考慮某個服務(wù)器實(shí)例失效的情況。如果負(fù)載均衡系統(tǒng)中的某個服務(wù)器實(shí)例失效,那么哈希算法中的哈希值空間將發(fā)生變化,進(jìn)而導(dǎo)致原本的服務(wù)實(shí)例分配結(jié)果將不再有效。在這種情況下,所有的請求將重新分配服務(wù)器實(shí)例。另外,在某些情況下,用戶的IP也可能在各個請求之間發(fā)生變化,進(jìn)而導(dǎo)致它所對應(yīng)的服務(wù)實(shí)例發(fā)生更改。當(dāng)然,不用擔(dān)心,后面對L7負(fù)載均衡服務(wù)器的講解會給您一個解決方案。

在確定了數(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方式的時候,負(fù)載均衡服務(wù)器以及各個服務(wù)實(shí)例必須在同一個網(wǎng)段上并使用同一個IP。在接收到數(shù)據(jù)的時候,負(fù)載均衡服務(wù)器將直接對這些數(shù)據(jù)包進(jìn)行轉(zhuǎn)發(fā)。而各個服務(wù)實(shí)例在處理完數(shù)據(jù)包之后可以將響應(yīng)返回給負(fù)載均衡服務(wù)器,也可以選擇將響應(yīng)直接發(fā)送給用戶,而不需要再經(jīng)過負(fù)載均衡服務(wù)器。后一種返回方式被稱為Direct Server Return。其運(yùn)行方式如下所示:

在該過程中,負(fù)載均衡服務(wù)器和各個服務(wù)實(shí)例都不需要對IP(Internet Protocol)層數(shù)據(jù)進(jìn)行任何更改就可以對其進(jìn)行轉(zhuǎn)發(fā)。使用這種轉(zhuǎn)發(fā)方式的負(fù)載均衡服務(wù)器的吞吐量非常高。反過來,這種組織方式也要求集群的搭建人員對TCP/IP等協(xié)議擁有足夠多的理解。

另一種轉(zhuǎn)發(fā)方式Tunnelling實(shí)際上與Direct routing類似。唯一的一點(diǎn)不同則是在負(fù)載均衡服務(wù)器和各個服務(wù)之間建立了一系列通道。軟件開發(fā)人員仍然可以選擇使用Direct Server Return來減輕負(fù)載均衡服務(wù)器的負(fù)載。

IP Address Translation則與前兩種方式非常不同。用戶所連接的目標(biāo)地址實(shí)際上是一個虛擬地址(VIP,Virtual IP)。而負(fù)載均衡服務(wù)器在接到該請求的時候?qū)⑵淠繕?biāo)地址轉(zhuǎn)化為服務(wù)實(shí)例所在的實(shí)際地址(RIP,Real IP),并將源地址更改為Load Balancer所在的地址。這樣在對請求處理完畢后,服務(wù)實(shí)例將會把響應(yīng)發(fā)送到負(fù)載均衡服務(wù)器。此時負(fù)載均衡服務(wù)器再將響應(yīng)的地址更改為VIP,并將該響應(yīng)返回給用戶。在這種轉(zhuǎn)發(fā)方式下,其運(yùn)行流程則如下所示:

有些細(xì)心的讀者會問:在消息傳遞的過程中,用戶所在的User IP已經(jīng)不在消息中存在了,那負(fù)載均衡服務(wù)器在傳回響應(yīng)的時候應(yīng)該如何恢復(fù)用戶的IP地址呢?實(shí)際上在這種轉(zhuǎn)發(fā)方式中,負(fù)載均衡服務(wù)器會維持一系列會話,以記錄每個經(jīng)由負(fù)載均衡服務(wù)器的正在處理的各個請求的相關(guān)信息。但是這些會話非常危險。如果將會話持續(xù)的時間設(shè)置得比較長,那么在一個高并發(fā)的負(fù)載均衡服務(wù)器上就需要維護(hù)過多的會話。反之如果將會話持續(xù)的時間設(shè)置得過短,那么就有可能導(dǎo)致ACK Storm發(fā)生。

先看會話持續(xù)時間較長的情況。假設(shè)當(dāng)前負(fù)載均衡服務(wù)器每秒鐘會接收到50000個請求,而且該負(fù)載均衡服務(wù)器的會話過期時間為2分鐘,那么其就需要保持6000000個會話。這些會話會占用負(fù)載均衡服務(wù)器的很大部分資源。而且在負(fù)載高峰期,其所消耗的資源可能會成倍地增長,會向服務(wù)器施加更多的壓力。

但是將會話持續(xù)時間設(shè)置得比較短則更為麻煩。這會導(dǎo)致用戶和負(fù)載均衡服務(wù)器之間產(chǎn)生ACK Storm,占用用戶和負(fù)載均衡服務(wù)器的大量帶寬。在一個TCP連接中,客戶端和服務(wù)端需要通過各自的Sequence Number來進(jìn)行溝通。如果負(fù)載均衡服務(wù)器上的會話快速地失效,那么其它TCP連接就有可能重用該會話。被重用的會話中客戶端和服務(wù)端的Sequence Number都會被重新生成。如果此時原有的用戶再次發(fā)送消息,那么負(fù)載均衡服務(wù)器將通過一個ACK消息通知客戶端其擁有的Sequence Number出錯。而在客戶端接受到該ACK消息之后,其將向負(fù)載均衡服務(wù)器發(fā)送另一個ACK消息通知服務(wù)端所擁有的Sequence Number出錯。服務(wù)端接受到該ACK消息后,將再次發(fā)送ACK消息到客戶端通知其所擁有的Sequence Number出錯……這樣客戶端和服務(wù)端之間就將持續(xù)地發(fā)送這種無意義的ACK消息,直到某個ACK消息在網(wǎng)絡(luò)傳輸過程中丟失為止。

因此乍一看來,使用IP Address Translation的方案是最容易的,但是相較于其它兩種方案,它卻是最危險也是維護(hù)成本最高的一種方案。

L7負(fù)載均衡

另一種較為常用的負(fù)載均衡解決方案則是L7負(fù)載均衡。顧名思義,其主要通過OSI模型中的第七層應(yīng)用層中的數(shù)據(jù)決定如何分發(fā)負(fù)載。

在運(yùn)行時,L7負(fù)載均衡服務(wù)器上的操作系統(tǒng)會將接收到的各個數(shù)據(jù)包組織成為用戶請求,并根據(jù)在該請求中所包含的的數(shù)據(jù)來決定由哪個服務(wù)實(shí)例來對該請求進(jìn)行處理。其運(yùn)行流程圖大致如下所示:

相較于L3/4負(fù)載均衡服務(wù)所使用的數(shù)據(jù),L7負(fù)載均衡服務(wù)所使用的應(yīng)用層數(shù)據(jù)更貼近服務(wù)本身,因此其具有更精確的負(fù)載均衡行為。

在前面對L3/4負(fù)載均衡的講解中我們已經(jīng)介紹過,對于某些具有關(guān)聯(lián)關(guān)系的各個請求,L3/4負(fù)載均衡服務(wù)器會根據(jù)某些算法(如計(jì)算IP的哈希值)來決定處理該請求的服務(wù)實(shí)例。但是這種方法并不是很穩(wěn)定。當(dāng)一個服務(wù)實(shí)例失效或用戶的IP發(fā)生變化的時候,用戶與服務(wù)實(shí)例之間的對應(yīng)關(guān)系就將發(fā)生改變。此時用戶原有的會話數(shù)據(jù)在新的服務(wù)實(shí)例上并不存在,進(jìn)而導(dǎo)致一系列問題。

其實(shí)產(chǎn)生這個問題的最根本原因就是用戶與服務(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í)際上就是分析用戶請求中的某個特定Cookie并根據(jù)其值決定需要分發(fā)到的目標(biāo)地址。其主要分為兩種方式:Cookie  Learning以及Cookie Insertion。

Cookie Learning是不具有侵入性的一種解決方案。其通過分析用戶與服務(wù)實(shí)例通訊過程中所傳遞的Cookie來決定如何分派負(fù)載:在用戶與服務(wù)第一次通訊時,負(fù)載均衡服務(wù)將找不到相應(yīng)的Cookie,因此其將會把該請求根據(jù)負(fù)載均衡算法分配到某個服務(wù)實(shí)例上。而在服務(wù)實(shí)例返回的時候,負(fù)載均衡服務(wù)器將會把對應(yīng)的Cookie以及服務(wù)實(shí)例的地址記錄在負(fù)載均衡服務(wù)器中。當(dāng)用戶再次與服務(wù)通訊時,負(fù)載均衡服務(wù)器就會根據(jù)Cookie中所記錄的數(shù)據(jù)找到前一次服務(wù)該用戶的服務(wù)實(shí)例,并將請求轉(zhuǎn)發(fā)到該服務(wù)實(shí)例上。

這么做的最大缺點(diǎn)就是對高可用性的支持很差。如果一旦負(fù)載均衡服務(wù)器失效,那么在該負(fù)載均衡服務(wù)器上所維護(hù)的Cookie和服務(wù)實(shí)例之間的匹配關(guān)系將全部丟失。這樣當(dāng)備份負(fù)載均衡服務(wù)器啟動之后,所有的用戶請求都將被定向到隨機(jī)的服務(wù)實(shí)例。

而另一個問題就是會話維護(hù)功能對內(nèi)存的消耗。與L3/4服務(wù)器上的會話維護(hù)不同,一個Cookie的失效時間可能非常長,至少在一次用戶使用中可能會持續(xù)幾個小時。對于一個訪問量達(dá)到每秒上萬次的系統(tǒng)而言,負(fù)載均衡服務(wù)器需要維護(hù)非常多的會話,甚至可能會將服務(wù)器的內(nèi)存消耗殆盡。反過來,如果將負(fù)載均衡服務(wù)器中的Cookie過期時間設(shè)置得太短,那么當(dāng)用戶重新訪問負(fù)載均衡服務(wù)器的時候,其將被導(dǎo)向到一個錯誤的服務(wù)實(shí)例。

除了Cookie Learning 之外,另一種常用的方法就是Cookie Insertion。其通過向響應(yīng)中添加Cookie以記錄被分派到的服務(wù)實(shí)例,并在下一次處理請求時根據(jù)該Cookie所保存的值來決定分發(fā)到的服務(wù)實(shí)例。在用戶與服務(wù)器進(jìn)行第一次通訊的時候,負(fù)載均衡服務(wù)器將找不到分派記錄所對應(yīng)的Cookie,因此其會根據(jù)負(fù)載均衡算法為該請求分配一個服務(wù)實(shí)例。在接收到服務(wù)實(shí)例所返回的數(shù)據(jù)之后,負(fù)載均衡服務(wù)器將會向響應(yīng)中插入一個Cookie,以記錄該服務(wù)實(shí)例的ID。當(dāng)用戶再次發(fā)送請求到負(fù)載均衡服務(wù)器時,其將根據(jù)該Cookie里所記錄的服務(wù)實(shí)例的ID派發(fā)該請求。

相較于Cookie Learning,Cookie Insertion不需要在內(nèi)存中維護(hù)Cookie與各個服務(wù)實(shí)例的對應(yīng)關(guān)系,而且在當(dāng)前負(fù)載均衡服務(wù)器失效的時候,備用負(fù)載均衡服務(wù)器也可以根據(jù)Cookie中所記錄的信息正確地派發(fā)各個請求。

當(dāng)然,Cookie Insertion也有缺陷。最常見的問題就是瀏覽器以及用戶自身對Cookie的限制。在Cookie Insertion中,我們需要插入一個額外的Cookie 來記錄分配給當(dāng)前用戶的服務(wù)實(shí)例。但是在某些瀏覽器中,特別是移動瀏覽器中,常常會限制Cookie的個數(shù),甚至只允許出現(xiàn)一個 Cookie。為了解決這個問題,負(fù)載均衡服務(wù)器也會使用一些其它方法。如Cookie Modification,即修改一個已有的Cookie使其包含服務(wù)實(shí)例的ID。

而在用戶禁用了Cookie的時候,Cookie Insertion將是完全失效的。此時負(fù)載均衡服務(wù)所能利用的將僅僅是JSESSIONID等信息。因此在一個L7負(fù)載均衡服務(wù)器中,Cookie Learning和Cookie Insertion常常同時使用:Cookie Learning會在用戶啟用Cookie的時候起主要作用,而在Cookie被用戶禁用的情況下則使用Cookie Learning來根據(jù)JSESSIONID來保持用戶與服務(wù)實(shí)例之間的關(guān)聯(lián)關(guān)系。

或許你會想:L3/4負(fù)載均衡服務(wù)器在處理各個關(guān)聯(lián)請求的時候是通過IP的哈希值來決定處理該請求的服務(wù)實(shí)例的。既然這些基于Cookie的解決方案能達(dá)到100%的準(zhǔn)確,為什么我們不在L3/4負(fù)載均衡服務(wù)器中使用它們呢?答案是:由于L3/4負(fù)載均衡服務(wù)器主要關(guān)注于數(shù)據(jù)包級別的轉(zhuǎn)發(fā),而Cookie信息則藏匿于數(shù)據(jù)包之中,因此L3/4負(fù)載均衡服務(wù)器很難決定單一的數(shù)據(jù)包該如何轉(zhuǎn)發(fā)。

例如在執(zhí)行Cookie Insertion操作的時候,原有數(shù)據(jù)包中的所有數(shù)據(jù)都將被后移。此時需要負(fù)載均衡服務(wù)器接收到所有數(shù)據(jù)包之后才能完成:

試想一下接收所有數(shù)據(jù)包所可能發(fā)生的事情吧。在網(wǎng)絡(luò)的一端發(fā)送多個數(shù)據(jù)包的時候,網(wǎng)絡(luò)的另一端所接收到的數(shù)據(jù)包的順序可能與原有的發(fā)送順序并不一致。甚至在網(wǎng)絡(luò)擁堵的時候,某些數(shù)據(jù)包可能會丟失,進(jìn)而再次加長接收到所有數(shù)據(jù)包所需要的時間。

因此相較于將數(shù)據(jù)包直接轉(zhuǎn)發(fā)的方法,等待所有的數(shù)據(jù)包到齊然后再插入Cookie的性能非常差。在后面對于解決方案的講解中您會看到,L3/4負(fù)載均衡服務(wù)器對于性能的要求一般來說是很高的,而L7負(fù)載均衡服務(wù)器則可以通過一個集群來解決自身的性能問題?;贒NS的負(fù)載均衡,L3/4負(fù)載均衡服務(wù)器以及L7負(fù)載均衡服務(wù)器常常協(xié)同工作,以組成一個具有高可用性以及高可擴(kuò)展性的系統(tǒng)。

SSL Farm

在上面的講解中,我們忽略了一個事情,那就是L7負(fù)載均衡服務(wù)器對于SSL的支持。在L7負(fù)載均衡服務(wù)器中,我們常常需要讀寫請求及響應(yīng)中的Cookie。但是如果通訊使用的是SSL連接,那么L7負(fù)載均衡服務(wù)器將無法對請求及響應(yīng)的內(nèi)容進(jìn)行讀寫操作。

解決該問題所曾經(jīng)使用的一個解決方案就是:將負(fù)載均衡服務(wù)器以反向代理的方式使用。在這種方案中,負(fù)載均衡服務(wù)器將擁有服務(wù)的證書,并可以通過證書中的密鑰對請求進(jìn)行解密。解密完成后,負(fù)載均衡服務(wù)器就可以開始嘗試讀取Cookie中的內(nèi)容并根據(jù)其所記錄的信息決定該請求所需要派發(fā)到的服務(wù)實(shí)例。在對該請求進(jìn)行派發(fā)的時候,負(fù)載均衡服務(wù)器可以不再使用SSL連接,進(jìn)而使得各個服務(wù)實(shí)例不再需要再次解密請求,提高服務(wù)實(shí)例的運(yùn)行效率。

在請求處理完畢之后,服務(wù)實(shí)例將通過服務(wù)實(shí)例與負(fù)載均衡服務(wù)器的非SSL連接返回一個響應(yīng)。在負(fù)載均衡服務(wù)器接收到該響應(yīng)之后,其將會把該響應(yīng)加密并通過SSL連接發(fā)出:

但是這樣做的問題在于,如果所有對SSL的處理都集中在L7負(fù)載均衡服務(wù)器上,那么它將會變成系統(tǒng)的瓶頸。繞過該問題的方法就是在L7負(fù)載均衡服務(wù)器之前使用一系列反向代理來負(fù)責(zé)SSL的編解碼操作。

此時整個系統(tǒng)的架構(gòu)將呈現(xiàn)如下的層次結(jié)構(gòu):

從上圖中可以看到,整個解決方案分為了四層。在用戶的請求到達(dá)了第一層的負(fù)載均衡服務(wù)器時,其將會把該請求根據(jù)自身的負(fù)載均衡算法轉(zhuǎn)發(fā)給處于第二層的專門負(fù)責(zé)SSL編解碼工作的反向代理。該代理會將傳入的由SSL連接所傳輸?shù)恼埱笥煞荢SL連接傳出。在請求到達(dá)第三層時,L7負(fù)載均衡服務(wù)器可以直接訪問這些請求所包含的Cookie,并根據(jù)Cookie中的內(nèi)容決定需要處理該請求的服務(wù)實(shí)例。

這么做的好處有很多。首先就是這些反向代理非常便宜,甚至只有常見負(fù)載均衡服務(wù)器的1/20左右的價格,卻在處理SSL連接上擁有幾乎相同的效率。除此之外,這些反向代理還提供了非常良好的擴(kuò)展性和高可用性。一旦負(fù)載均衡系統(tǒng)在處理SSL連接的能力上顯得有些吃力,我們就隨時可以向系統(tǒng)中添加新的反向代理。而一旦其中一個反向代理失效,那么其它反向代理可以通過多承擔(dān)一些負(fù)載來保證系統(tǒng)的安全運(yùn)行。

需要考慮的問題

在提出具體的負(fù)載均衡解決方案之前,我們需要首先講解一下在設(shè)計(jì)負(fù)載均衡系統(tǒng)時我們所需要考慮的一些事情。

首先要說的就是要在負(fù)載均衡系統(tǒng)設(shè)計(jì)時留意它的高可用性及擴(kuò)展性。在一開始的講解中,我們就已經(jīng)提到過通過使用負(fù)載均衡,由眾多服務(wù)器實(shí)例所組成的服務(wù)具有很高的可用性及擴(kuò)展性。當(dāng)其中一個服務(wù)實(shí)例失效的時候,其它服務(wù)實(shí)例可以幫助它分擔(dān)一部分工作。而在總服務(wù)容量顯得有些緊張的時候,我們可以向服務(wù)中添加新的服務(wù)實(shí)例以擴(kuò)展服務(wù)的總?cè)萘俊?/span>

但是由于所有的數(shù)據(jù)傳輸都需要經(jīng)過負(fù)載均衡服務(wù)器,因此負(fù)載均衡服務(wù)器一旦失效,那么整個系統(tǒng)就將無法使用。也就是說,負(fù)載均衡服務(wù)器的可用性影響著整個系統(tǒng)的高可用性。

解決這個問題的方法要根據(jù)負(fù)載均衡服務(wù)器的類型來討論。對于L3/4負(fù)載均衡服務(wù)器而言,為了能夠讓整個系統(tǒng)不失效,業(yè)界中的常用方法是在系統(tǒng)中使用一對負(fù)載均衡服務(wù)器。當(dāng)其中一個負(fù)載均衡服務(wù)器失效的時候,另一個還能夠?yàn)檎麄€系統(tǒng)提供負(fù)載均衡服務(wù)。這一對負(fù)載均衡服務(wù)器可以按照Active-Passive模式使用,也可以按照Active-Active模式使用。

在Active-Passive模式中,一個負(fù)載均衡服務(wù)器處于半休眠狀態(tài)。其將會通過向另外一個負(fù)載均衡服務(wù)器發(fā)送心跳消息來探測對方的可用性。當(dāng)正在工作的負(fù)載均衡服務(wù)器不再響應(yīng)心跳的時候,那么心跳應(yīng)用將會把負(fù)載均衡服務(wù)器從半休眠狀態(tài)喚醒,接管負(fù)載均衡服務(wù)器的IP并開始執(zhí)行負(fù)載均衡功能。

而在Active-Active模式中,兩臺負(fù)載均衡服務(wù)器會同時工作。如果其中一臺服務(wù)器發(fā)生了故障,那么另一臺服務(wù)器將會承擔(dān)所有的工作:

可以說,兩者各有千秋。相較而言,Active-Active模式具有較好的抵抗訪問量大幅波動的情況。例如在通常情況下,兩個服務(wù)器的負(fù)載都在30%左右,但是在服務(wù)使用的高峰時間,訪問量可能是平時的兩倍,因此兩個服務(wù)器的負(fù)載就將達(dá)到60%左右,仍處于系統(tǒng)可以處理的范圍內(nèi)。如果我們使用的是Active-Passive模式,那么平時的負(fù)載就將達(dá)到60%,而在高峰時間的負(fù)載將達(dá)到負(fù)載均衡服務(wù)器容量的120%,進(jìn)而使得服務(wù)無法處理所有的用戶請求。

反過來,Active-Active模式也有不好的地方,那就是容易導(dǎo)致管理上的疏忽。例如在一個使用了Active-Active模式的系統(tǒng)中,兩個負(fù)載均衡服務(wù)器的負(fù)載常年都在60%左右。那么一旦其中的一個負(fù)載均衡服務(wù)器失效了,那么剩下的唯一一個服務(wù)器同樣將無法處理所有的用戶請求。

或許你會問:L3/4負(fù)載均衡服務(wù)器一定要有兩個么?其實(shí)主要由各負(fù)載均衡服務(wù)器產(chǎn)品自身來決定的。在前面我們已經(jīng)講過,實(shí)際上探測負(fù)載均衡服務(wù)器的可用性實(shí)際上需要很復(fù)雜的測試邏輯。因此如果一旦我們在一個負(fù)載均衡系統(tǒng)中使用了過多的L3/4負(fù)載均衡服務(wù)器,那么這些負(fù)載均衡服務(wù)器之間所發(fā)送的各種心跳測試將消耗非常多的資源。同時由于很多L3/4負(fù)載均衡服務(wù)器本身是基于硬件的,因此它能夠非??焖俚毓ぷ鳎踔量梢赃_(dá)到與其所支持的網(wǎng)絡(luò)帶寬所匹配的處理能力。因此在一般情況下,L3/4負(fù)載均衡服務(wù)器是成對使用的。

如果L3/4負(fù)載均衡服務(wù)器真的接近其負(fù)載極限,那么我們還可以通過DNS負(fù)載均衡來分散請求:

這種方法不僅僅可以解決擴(kuò)展性的問題,更可以利用DNS的一個特性來提高用戶體驗(yàn):DNS可以根據(jù)用戶所在的區(qū)域選擇距離用戶最近的服務(wù)器。這在一個全球性的服務(wù)中尤為有效。畢竟一個中國用戶訪問在中國架設(shè)的服務(wù)實(shí)例要比訪問在美國架設(shè)的服務(wù)實(shí)例快得多。

反過來由于L7負(fù)載均衡服務(wù)器主要是基于軟件的,因此很多L7負(fù)載均衡服務(wù)器允許用戶創(chuàng)建較為復(fù)雜的負(fù)載均衡服務(wù)器系統(tǒng)。例如定義一個具有兩個啟用而有一個備用的一組L7負(fù)載均衡服務(wù)器。

講解完了高可用性,我們就來介紹一下負(fù)載均衡服務(wù)器的擴(kuò)展性。其實(shí)在上面我們剛剛介紹過,L3/4負(fù)載均衡服務(wù)器擁有很高的性能,因此一般的服務(wù)所使用的負(fù)載均衡系統(tǒng)不會遇到需要擴(kuò)展性的問題。但是一旦出現(xiàn)了需要擴(kuò)展的情況,那么使用DNS負(fù)載均衡就可以達(dá)到較好的擴(kuò)展性。而L7負(fù)載均衡則更為靈活,因此擴(kuò)展性更不是問題。

但是一個負(fù)載均衡系統(tǒng)不可能都是由L3/4負(fù)載均衡服務(wù)器組成的,也不可能只由L7負(fù)載均衡服務(wù)器組成的。這是因?yàn)閮烧咴谛阅芎蛢r格上都具有非常大的差異。一個L3/4負(fù)載均衡服務(wù)器實(shí)際上價格非常昂貴,常常達(dá)到上萬美元。而L7負(fù)載均衡服務(wù)器則可以使用廉價服務(wù)器搭建。L3/4負(fù)載均衡服務(wù)器常常具有非常高的性能,而L7負(fù)載均衡服務(wù)器則常常通過組成一個集群來達(dá)到較高的整體性能。

在設(shè)計(jì)負(fù)載均衡系統(tǒng)時,還有一點(diǎn)需要考慮的那就是服務(wù)的動靜分離。我們知道,一個服務(wù)常常由動態(tài)請求和靜態(tài)請求共同組成。這兩種請求具有非常不同的特點(diǎn):一個動態(tài)請求常常需要大量的計(jì)算而傳輸?shù)臄?shù)據(jù)常常不是很多,而一個靜態(tài)的請求常常需要傳輸大量的數(shù)據(jù)而不需要太多的計(jì)算。不同的服務(wù)容器對這些請求的表現(xiàn)差異很大。因此很多服務(wù)常常將其所包含的服務(wù)實(shí)例分為兩部分,分別用來處理靜態(tài)請求和動態(tài)請求,并使用適合的服務(wù)容器提供服務(wù)。在這種情況下,靜態(tài)請求常常被置于特定的路徑下,如“/static”。這樣負(fù)載均衡服務(wù)器就可以根據(jù)請求所發(fā)送到的路徑而將動態(tài)請求和靜態(tài)請求進(jìn)行適當(dāng)?shù)剞D(zhuǎn)發(fā)。

最后要提到的就是L3/4負(fù)載均衡服務(wù)器的一個軟件實(shí)現(xiàn)LVS(Linux Virtual Server)。相較于硬件實(shí)現(xiàn),軟件實(shí)現(xiàn)需要做很多額外的工作,例如對數(shù)據(jù)包的解碼,為處理數(shù)據(jù)包分配內(nèi)存等等呢個。因此其性能常常只是具有相同硬件能力的L3/4負(fù)載均衡服務(wù)器的1/5到1/10。鑒于其只具有有限的性能但是搭建起來成本很低,如利用已有的在Lab里閑置的機(jī)器等,因此其常常在服務(wù)規(guī)模不是很大的時候作為臨時替代方案使用。

負(fù)載均衡解決方案

在文章的最后,我們將給出一系列常見的負(fù)載均衡解決方案,以供大家參考。

在一般情況下,一個服務(wù)的負(fù)載常常是通過某些方式逐漸增長的。相應(yīng)地,這些服務(wù)所擁有的負(fù)載均衡系統(tǒng)常常是從小到大逐漸演化的。因此我們也將會按照從小到大的方式逐次介紹這些負(fù)載均衡系統(tǒng)。

首先是最簡單的包含一對L7負(fù)載均衡服務(wù)器的系統(tǒng):

如果服務(wù)的負(fù)載逐漸增大,那么該系統(tǒng)中唯一的L7負(fù)載均衡服務(wù)器很容易變成瓶頸。此時我們可以通過添加一個SSL Farm以及運(yùn)行LVS的服務(wù)器來解決問題:

如果我們還要應(yīng)對增長的負(fù)載,那么就需要使用真正的基于硬件的L3/4負(fù)載均衡服務(wù)器來替代LVS,并增加各層的容量:

由于該解決方案的下面三層基本都有理論上無限的擴(kuò)展性,因此最容易出現(xiàn)過載的就是最上面的L3/4負(fù)載均衡服務(wù)器。在這種情況下,我們就需要使用DNS來分配負(fù)載了:

轉(zhuǎn)發(fā)是對作者最大的支持?。?!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多