企業級負載平衡簡介

  在以前的一篇文章《放好你的密碼 - 從芝麻金融被攻破提及》中,一位讀者在評論中提出了「若是整個過程速度比較慢登錄會有問題」這樣一條評論。雖說我對文章的正確性頗有把握,但也仍須要仔細思考是否本身哪裏沒有說清楚。在這個思考過程當中,我想起了一個很是值得一說的話題,那就是負載平衡。html

  在那篇文章中咱們說到,要安全地管理好密碼,計算密碼哈希所使用的迭代次數應該儘量地大,從而使得單次哈希計算的速度變長,增長惡意人員破解密碼的難度。反過來,若是有一百我的或者一千我的同時執行登錄操做,那麼這麼繁瑣的哈希計算將致使登錄服務器產生「忙不過來」的狀況。此時咱們就須要使用負載平衡將登錄請求分散到多個登錄服務器上,以下降單個服務器的負載。算法

 

負載平衡簡介瀏覽器

  或許有些讀者仍然對負載平衡這個名詞感到陌生,那麼咱們就花一小段篇幅來說解一下到底什麼是負載平衡。緩存

  在一個大型網站中,在線用戶有時可能有幾千個甚至上萬個之多。若是一個用戶的請求須要服務使用0.02秒來處理,那麼該服務實例每秒鐘將只能處理50個這樣的請求,每分鐘也只能處理3000個。若是該服務是一個用戶很是經常使用的功能,如瀏覽網站的產品列表,那麼很顯然單個服務實例已經沒法支持該網站的運營。在這種狀況下,咱們就須要對該服務進行擴容。安全

  擴容主要分爲Scale Up和Scale Out兩種,分別對應着加強單個服務的服務能力以及加強服務數量。在某些狀況下,Scale Up是一個較爲簡單的操做,例如爲該服務所在的服務器添加更大的內存。可是任意一個服務器所能提供的能力實際上都受到其自身物理硬件能力的限制,尤爲是具備越高性能的服務器其單位服務能力的價格越爲昂貴,所以咱們就須要使用Scale  Out方式將工做量分攤到多個服務器之中:服務器

  就如上圖所顯示的那樣,當服務器的負載過多而來不及處理的時候,服務器就處於一種過載的狀態。在該狀態的服務經常會出現響應速度慢甚至無響應的狀況。而在執行了Scale Out以後,咱們將會使用多個服務器同時處理用戶的請求。在該解決方案中,咱們須要使用一臺特定的設備將這些請求分發到各個服務器。該設備會根據其內部所包含的請求分發邏輯來決定如何對這些請求進行分發,以免出現單個服務器過載的狀況。這些用來對請求進行分發的設備實際上就是負載平衡服務器。網絡

  固然,咱們不會等到服務器真正過載了纔去解決這個問題。在服務的平常運維中,咱們在服務器的平均負載和峯值負載達到某個特定閾值時就須要考慮是否須要爲相應服務進行擴容。架構

  一旦一個服務使用了負載平衡系統,那麼它將在高可用性以及擴展性上獲得極大的加強。這也是咱們使用負載平衡解決方案的最重要緣由。例如對於一個擁有三臺服務器的負載平衡系統,若是其中一臺發生了故障,那麼負載平衡服務器能夠經過向各個服務發送心跳等方式得知它們的異常,進而再也不向這個發生了故障的服務器分發任務:併發

  而若是當前負載平衡系統中所負擔的服務容量已經超過了閾值,那麼咱們能夠簡單地經過在負載平衡系統中添加服務器來解決這個問題:運維

  這樣,每一個服務器所須要處理的任務就相對減小了,從而減輕了單個服務器的負擔。

 

基於DNS的負載平衡

  OK,在瞭解了負載平衡系統的大體組成及使用方式以後,咱們就來看看各類負載解決方案。

  當前業界中所最常使用的負載平衡解決方案主要分爲三種:基於DNS的負載平衡,L3/4負載平衡,也便是基於網絡層的負載平衡,以及L7負載平衡,即基於應用層的負載平衡。在這些解決方案中,基於DNS的負載平衡是最簡單的,也是最先出現的一種負載平衡解決方案。

  當咱們經過在瀏覽器的地址欄中鍵入域名來訪問某個網站時,瀏覽器將首先查找本地的DNS緩存是否擁有該域名所對應的IP地址。若是有,那麼瀏覽器將嘗試直接使用該IP地址訪問該網站的內容。若是本地DNS緩存中沒有該域名所對應的IP地址,那麼它將向DNS發送一個請求,以得到該域名所對應的IP並添加到本地DNS緩存中。

  而在DNS中,一個域名可能和多個IP地址綁定。在這種狀況下,DNS響應將會按照Round Robin方式返回這些IP地址的列表。例如在屢次經過nslookup或host等命令來查看特定域名所對應的IP時,其可能的返回以下(因國內網絡緣由,您須要FQ再進行試驗):

 

  $ 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請求所返回的結果會按照Round Robin進行輪換,進而使得不一樣的用戶訪問不一樣的IP地址,平衡各個服務器的負載。

  雖然這種負載平衡解決方案很是容易實現,可是它有一個致命的缺點:爲了減小DNS請求的次數以提升訪問效率,瀏覽器經常緩存了DNS查詢的結果。若是一個IP處的服務失效,那麼瀏覽器可能仍會根據DNS緩存中所記錄的信息向該不可用的服務發送請求(不一樣的瀏覽器可能有不一樣的行爲)。雖說整個服務只有一處IP所對應的服務失效了,可是從用戶的角度看來該網站已經不可訪問。所以基於DNS的負載平衡方案並不能做爲一個獨立的負載平衡解決方案來提供高可用性的保障,而是做爲其它負載平衡解決方案的補充方案來使用。

 

L3/4負載平衡

  另外一種較爲常見的負載平衡則是L3/4負載平衡。這裏的L3/4實際上指的就是負載平衡服務器會根據OSI模型中的第三層網絡層(Network Layer)和第四層傳輸層(Transport Layer)所包含的數據來進行負載平衡操做。在這種負載平衡服務器中,這些數據主要包含數據包的IP頭和TCP、UDP等協議的協議頭:

  L3/4負載平衡服務器的工做原理很是簡單:在數據到達時,負載平衡服務器將根據自身算法以及OSI模型三四層所包含的數據決定須要處理該數據的服務實例並將其轉發。

  整個負載平衡的運行包含三方面內容:負載平衡服務器須要知道當前有效的服務實例到底有哪些,並根據自身的分派算法來決定須要處理數據的服務實例,根據分派算法的計算結果將數據發送到目標服務實例上。

  首先來看看負載平衡服務器是如何肯定服務實例的有效性的。爲了可以保證從負載平衡服務器所派發的數據包能被它後面的服務器集羣正常處理,負載平衡服務器須要週期性地發送狀態查詢請求以探測到底哪些服務實例正在有效地工做。這種狀態查詢請求經常會超出不少人的認知:若是服務實例崩潰可是承載它的操做系統正常工做,那麼該操做系統仍然會正常響應負載平衡服務器所發出的Ping命令,只是此時TCP鏈接會失敗;若是服務實例並無崩潰,而只是掛起,那麼它仍然能夠接受TCP鏈接,只是沒法接收HTTP請求。

  因爲這種狀態查詢請求其實是特定於服務實例的具體實現,所以不少負載平衡服務器都容許用戶添加自定義腳本以執行特定於服務實例的查詢。這些狀態查詢請求經常包含了不少測試,甚至會嘗試從服務實例中返回數據。

  一旦負載平衡服務器發現其所管理的某個服務實例再也不有效,那麼它就不會再將任何數據轉發給該服務實例,直到該服務實例迴歸正常狀態。在這種狀況下,其它各個服務實例就須要分擔失效服務器所本來承擔的工做。

  這裏須要注意的一點是,在某個服務實例失效之後,整個系統仍應該具備足夠的總容量以處理負載。舉例來講,假如一個負載平衡服務器管理了三個具備相同能力的服務實例,並且這三個服務實例各自的負載都在80%左右。若是其中一個服務實例失效,那麼全部的負載都須要由其它兩個服務實例來完成。每一個服務實例就須要承擔120%的負載,遠超過了它所具備的負載能力。這種狀況的直接後果就是,服務顯得很是不穩定,並經常有系統超時,應用沒法正常工做的狀況出現。

  OK。 如今假設咱們的負載平衡服務器有一個設計良好的狀態查詢請求,那麼它就會根據其所使用的負載平衡算法來爲工做的服務實例分配負載。對於初次接觸到負載平衡功能的人來講,最多見的誤區就是認爲負載平衡服務器會根據各個服務實例的響應速度或負載情況來決定請求須要到達的服務實例。

  一般狀況下,Round Robin算法是最經常使用也是表現最好的負載平衡算法。若是各個服務實例的容量並不相同,那麼負載平衡服務器會使用Weighted Round Robin算法,即根據各個服務實例的實際能力來安比例地分配負載。在某些商業負載平衡服務器中,其的確會根據當前服務實例的負載以及響應時間等因素對這些分配比例自動進行微小地調整,可是它們並非決定性的因素。

  若是單純地使用Round Robin算法,那麼具備關聯關係的各個請求將可能被分配到不一樣的服務實例上。所以不少負載平衡服務器容許根據數據的特定特徵對這些負載進行分配,如使用一種哈希算法來對用戶所在的IP進行計算,並以計算結果決定須要分配到的服務實例。

  一樣地,咱們也須要考慮某個服務器實例失效的狀況。若是負載平衡系統中的某個服務器實例失效,那麼哈希算法中的哈希值空間將發生變化,進而致使本來的服務實例分配結果將再也不有效。在這種狀況下,全部的請求將從新分配服務器實例。另外,在某些狀況下,用戶的IP也可能在各個請求之間發生變化,進而致使它所對應的服務實例發生更改。固然,不用擔憂,後面對L7負載平衡服務器的講解會給您一個解決方案。

  在肯定了數據包的目標地址後,負載平衡服務器所須要作的事情就是將它們轉發到目標實例了。負載平衡服務器所使用的轉發方式主要分爲三種:Direct routing,Tunnelling以及IP address translation。

  在使用Direct routing方式的時候,負載平衡服務器以及各個服務實例必須在同一個網段上並使用同一個IP。在接收到數據的時候,負載平衡服務器將直接對這些數據包進行轉發。而各個服務實例在處理完數據包以後能夠將響應返回給負載平衡服務器,也能夠選擇將響應直接發送給用戶,而不須要再通過負載平衡服務器。後一種返回方式被稱爲Direct Server Return。其運行方式以下所示:

  在該過程當中,負載平衡服務器和各個服務實例都不須要對IP(Internet Protocol)層數據進行任何更改就能夠對其進行轉發。使用這種轉發方式的負載平衡服務器的吞吐量很是高。反過來,這種組織方式也要求集羣的搭建人員對TCP/IP等協議擁有足夠多的理解。

  另外一種轉發方式Tunnelling實際上與Direct routing相似。惟一的一點不一樣則是在負載平衡服務器和各個服務之間創建了一系列通道。軟件開發人員仍然能夠選擇使用Direct Server Return來減輕負載平衡服務器的負載。

  IP Address Translation則與前兩種方式很是不一樣。用戶所鏈接的目標地址其實是一個虛擬地址(VIP,Virtual IP)。而負載平衡服務器在接到該請求的時候將會將其目標地址轉化爲服務實例所在的實際地址(RIP,Real IP),並將源地址更改成Load Balancer所在的地址。這樣在對請求處理完畢後,服務實例將會把響應發送到負載平衡服務器。此時負載平衡服務器再將響應的地址更改成VIP,並將該響應返回給用戶。在這種轉發方式下,其運行流程則以下所示:

  有些細心的讀者會問:在消息傳遞的過程當中,用戶所在的User IP已經不在消息中存在了,那負載平衡服務器在傳回響應的時候應該如何恢復用戶的IP地址呢?實際上在這種轉發方式中,負載平衡服務器會維持一系列會話,以記錄每一個經由負載平衡服務器的正在處理的各個請求的相關信息。可是這些會話很是危險。若是將會話持續的時間設置得比較長,那麼在一個高併發的負載平衡服務器上就須要維護過多的會話。反之若是將會話持續的時間設置得太短,那麼就有可能致使ACK Storm發生。

  先看會話持續時間較長的狀況。假設當前負載平衡服務器每秒鐘會接收到50000個請求,並且該負載平衡服務器的會話過時時間爲2分鐘,那麼其就須要保持6000000個會話。這些會話會佔用負載平衡服務器的很大部分資源。並且在負載高峯期,其所消耗的資源可能會成倍地增加,會向服務器施加更多的壓力。

  可是將會話持續時間設置得比較短則更爲麻煩。這會致使用戶和負載平衡服務器之間產生ACK Storm,佔用用戶和負載平衡服務器的大量帶寬。在一個TCP鏈接中,客戶端和服務端須要經過各自的Sequence Number來進行溝通。若是負載平衡服務器上的會話快速地失效,那麼其它TCP鏈接就有可能重用該會話。被重用的會話中客戶端和服務端的Sequence Number都會被從新生成。若是此時原有的用戶再次發送消息,那麼負載平衡服務器將經過一個ACK消息通知客戶端其擁有的Sequence Number出錯。而在客戶端接受到該ACK消息以後,其將向負載平衡服務器發送另外一個ACK消息通知服務端所擁有的Sequence Number出錯。服務端接受到該ACK消息後,將再次發送ACK消息到客戶端通知其所擁有的Sequence Number出錯……這樣客戶端和服務端之間就將持續地發送這種無心義的ACK消息,直到某個ACK消息在網絡傳輸過程當中丟失爲止。

  所以乍一看來,使用IP Address Translation的方案是最容易的,可是相較於其它兩種方案,它倒是最危險也是維護成本最高的一種方案。

 

L7負載平衡

  另外一種較爲經常使用的負載平衡解決方案則是L7負載平衡。顧名思義,其主要經過OSI模型中的第七層應用層中的數據決定如何分發負載。

  在運行時,L7負載平衡服務器上的操做系統會將接收到的各個數據包組織成爲用戶請求,並根據在該請求中所包含的的數據來決定由哪一個服務實例來對該請求進行處理。其運行流程圖大體以下所示:

  相較於L3/4負載平衡服務所使用的數據,L7負載平衡服務所使用的應用層數據更貼近服務自己,所以其具備更精確的負載平衡行爲。

  在前面對L3/4負載平衡的講解中咱們已經介紹過,對於某些具備關聯關係的各個請求,L3/4負載平衡服務器會根據某些算法(如計算IP的哈希值)來決定處理該請求的服務實例。可是這種方法並非很穩定。當一個服務實例失效或用戶的IP發生變化的時候,用戶與服務實例之間的對應關係就將發生改變。此時用戶原有的會話數據在新的服務實例上並不存在,進而致使一系列問題。

  其實產生這個問題的最根本緣由就是用戶與服務實例之間的關聯關係是經過某些外部環境建立的,而並不是由用戶/服務實例自己來管理。所以它不能抵禦外部環境變化的衝擊。若是要在用戶和服務實例之間創建穩定的關聯關係,那麼就須要一種穩定的在用戶和服務實例之間傳遞的數據。在Web服務中,這種數據就是Cookie。

  簡單地說,基於Cookie的負載平衡服務實際上就是分析用戶請求中的某個特定Cookie並根據其值決定須要分發到的目標地址。其主要分爲兩種方式:Cookie  Learning以及Cookie Insertion。

  Cookie Learning是不具備侵入性的一種解決方案。其經過分析用戶與服務實例通信過程當中所傳遞的Cookie來決定如何分派負載:在用戶與服務第一次通信時,負載平衡服務將找不到相應的Cookie,所以其將會把該請求根據負載平衡算法分配到某個服務實例上。而在服務實例返回的時候,負載平衡服務器將會把對應的Cookie以及服務實例的地址記錄在負載平衡服務器中。當用戶再次與服務通信時,負載平衡服務器就會根據Cookie中所記錄的數據找到前一次服務該用戶的服務實例,並將請求轉發到該服務實例上。

  這麼作的最大缺點就是對高可用性的支持不好。若是一旦負載平衡服務器失效,那麼在該負載平衡服務器上所維護的Cookie和服務實例之間的匹配關係將所有丟失。這樣當備份負載平衡服務器啓動以後,全部的用戶請求都將被定向到隨機的服務實例。

  而另外一個問題就是會話維護功能對內存的消耗。與L3/4服務器上的會話維護不一樣,一個Cookie的失效時間可能很是長,至少在一次用戶使用中可能會持續幾個小時。對於一個訪問量達到每秒上萬次的系統而言,負載平衡服務器須要維護很是多的會話,甚至可能會將服務器的內存消耗殆盡。反過來,若是將負載平衡服務器中的Cookie過時時間設置得過短,那麼當用戶從新訪問負載平衡服務器的時候,其將被導向到一個錯誤的服務實例。

  除了Cookie Learning 以外,另外一種經常使用的方法就是Cookie Insertion。其經過向響應中添加Cookie以記錄被分派到的服務實例,並在下一次處理請求時根據該Cookie所保存的值來決定分發到的服務實例。在用戶與服務器進行第一次通信的時候,負載平衡服務器將找不到分派記錄所對應的Cookie,所以其會根據負載平衡算法爲該請求分配一個服務實例。在接收到服務實例所返回的數據以後,負載平衡服務器將會向響應中插入一個Cookie,以記錄該服務實例的ID。當用戶再次發送請求到負載平衡服務器時,其將根據該Cookie裏所記錄的服務實例的ID派發該請求。

  相較於Cookie Learning,Cookie Insertion不須要在內存中維護Cookie與各個服務實例的對應關係,並且在當前負載平衡服務器失效的時候,備用負載平衡服務器也能夠根據Cookie中所記錄的信息正確地派發各個請求。

  固然,Cookie Insertion也有缺陷。最多見的問題就是瀏覽器以及用戶自身對Cookie的限制。在Cookie Insertion中,咱們須要插入一個額外的Cookie 來記錄分配給當前用戶的服務實例。可是在某些瀏覽器中,特別是移動瀏覽器中,經常會限制Cookie的個數,甚至只容許出現一個 Cookie。爲了解決這個問題,負載平衡服務器也會使用一些其它方法。如Cookie Modification,即修改一個已有的Cookie使其包含服務實例的ID。

  而在用戶禁用了Cookie的時候,Cookie Insertion將是徹底失效的。此時負載平衡服務所能利用的將僅僅是JSESSIONID等信息。所以在一個L7負載平衡服務器中,Cookie Learning和Cookie Insertion經常同時使用:Cookie Learning會在用戶啓用Cookie的時候起主要做用,而在Cookie被用戶禁用的狀況下則使用Cookie Learning來根據JSESSIONID來保持用戶與服務實例之間的關聯關係。

  或許您會想:L3/4負載平衡服務器在處理各個關聯請求的時候是經過IP的哈希值來決定處理該請求的服務實例的。既然這些基於Cookie的解決方案能達到100%的準確,爲何咱們不在L3/4負載平衡服務器中使用它們呢?答案是:因爲L3/4負載平衡服務器主要關注於數據包級別的轉發,而Cookie信息則藏匿於數據包之中,所以L3/4負載平衡服務器很難決定單一的數據包該如何轉發。

  例如在執行Cookie Insertion操做的時候,原有數據包中的全部數據都將被後移。此時須要負載平衡服務器接收到全部數據包以後才能完成:

  試想一下接收全部數據包所可能發生的事情吧。在網絡的一端發送多個數據包的時候,網絡的另外一端所接收到的數據包的順序可能與原有的發送順序並不一致。甚至在網絡擁堵的時候,某些數據包可能會丟失,進而再次加長接收到全部數據包所須要的時間。

  所以相較於將數據包直接轉發的方法,等待全部的數據包到齊而後再插入Cookie的性能很是差。在後面對於解決方案的講解中您會看到,L3/4負載平衡服務器對於性能的要求通常來講是很高的,而L7負載平衡服務器則能夠經過一個集羣來解決自身的性能問題。基於DNS的負載平衡,L3/4負載平衡服務器以及L7負載平衡服務器經常協同工做,以組成一個具備高可用性以及高可擴展性的系統。

 

SSL Farm

  在上面的講解中,咱們忽略了一個事情,那就是L7負載平衡服務器對於SSL的支持。在L7負載平衡服務器中,咱們經常須要讀寫請求及響應中的Cookie。可是若是通信使用的是SSL鏈接,那麼L7負載平衡服務器將沒法對請求及響應的內容進行讀寫操做。

  解決該問題所曾經使用的一個解決方案就是:將負載平衡服務器以反向代理的方式使用。在這種方案中,負載平衡服務器將擁有服務的證書,並能夠經過證書中的密鑰對請求進行解密。解密完成後,負載平衡服務器就能夠開始嘗試讀取Cookie中的內容並根據其所記錄的信息決定該請求所須要派發到的服務實例。在對該請求進行派發的時候,負載平衡服務器能夠再也不使用SSL鏈接,進而使得各個服務實例再也不須要再次解密請求,提升服務實例的運行效率。

  在請求處理完畢以後,服務實例將經過服務實例與負載平衡服務器的非SSL鏈接返回一個響應。在負載平衡服務器接收到該響應以後,其將會把該響應加密並經過SSL鏈接發出:

  可是這樣作的問題在於,若是全部對SSL的處理都集中在L7負載平衡服務器上,那麼它將會變成系統的瓶頸。繞過該問題的方法就是在L7負載平衡服務器以前使用一系列反向代理來負責SSL的編解碼操做。

  此時整個系統的架構將呈現以下的層次結構:

  從上圖中能夠看到,整個解決方案分爲了四層。在用戶的請求到達了第一層的負載平衡服務器時,其將會把該請求根據自身的負載平衡算法轉發給處於第二層的專門負責SSL編解碼工做的反向代理。該代理會將傳入的由SSL鏈接所傳輸的請求由非SSL鏈接傳出。在請求到達第三層時,L7負載平衡服務器能夠直接訪問這些請求所包含的Cookie,並根據Cookie中的內容決定須要處理該請求的服務實例。

  這麼作的好處有不少。首先就是這些反向代理很是便宜,甚至只有常見負載平衡服務器的1/20左右的價格,卻在處理SSL鏈接上擁有幾乎相同的效率。除此以外,這些反向代理還提供了很是良好的擴展性和高可用性。一旦負載平衡系統在處理SSL鏈接的能力上顯得有些吃力,咱們就隨時能夠向系統中添加新的反向代理。而一旦其中一個反向代理失效,那麼其它反向代理能夠經過多承擔一些負載來保證系統的安全運行。

 

須要考慮的問題

  在提出具體的負載平衡解決方案以前,咱們須要首先講解一下在設計負載平衡系統時咱們所須要考慮的一些事情。

  首先要說的就是要在負載平衡系統設計時留意它的高可用性及擴展性。在一開始的講解中,咱們就已經提到過經過使用負載平衡,由衆多服務器實例所組成的服務具備很高的可用性及擴展性。當其中一個服務實例失效的時候,其它服務實例能夠幫助它分擔一部分工做。而在總服務容量顯得有些緊張的時候,咱們能夠向服務中添加新的服務實例以擴展服務的總容量。

  可是因爲全部的數據傳輸都須要通過負載平衡服務器,所以負載平衡服務器一旦失效,那麼整個系統就將沒法使用。也就是說,負載平衡服務器的可用性影響着整個系統的高可用性。

  解決這個問題的方法要根據負載平衡服務器的類型來討論。對於L3/4負載平衡服務器而言,爲了可以讓整個系統不失效,業界中的經常使用方法是在系統中使用一對負載平衡服務器。當其中一個負載平衡服務器失效的時候,另外一個還可以爲整個系統提供負載平衡服務。這一對負載平衡服務器能夠按照Active-Passive模式使用,也能夠按照Active-Active模式使用。

  在Active-Passive模式中,一個負載平衡服務器處於半休眠狀態。其將會經過向另一個負載平衡服務器發送心跳消息來探測對方的可用性。當正在工做的負載平衡服務器再也不響應心跳的時候,那麼心跳應用將會把負載平衡服務器從半休眠狀態喚醒,接管負載平衡服務器的IP並開始執行負載平衡功能。

  而在Active-Active模式中,兩臺負載平衡服務器會同時工做。若是其中一臺服務器發生了故障,那麼另外一臺服務器將會承擔全部的工做:

  能夠說,二者各有千秋。相較而言,Active-Active模式具備較好的抵抗訪問量大幅波動的狀況。例如在一般狀況下,兩個服務器的負載都在30%左右,可是在服務使用的高峯時間,訪問量多是平時的兩倍,所以兩個服務器的負載就將達到60%左右,仍處於系統能夠處理的範圍內。若是咱們使用的是Active-Passive模式,那麼平時的負載就將達到60%,而在高峯時間的負載將達到負載平衡服務器容量的120%,進而使得服務沒法處理全部的用戶請求。

  反過來,Active-Active模式也有很差的地方,那就是容易致使管理上的疏忽。例如在一個使用了Active-Active模式的系統中,兩個負載平衡服務器的負載常年都在60%左右。那麼一旦其中的一個負載平衡服務器失效了,那麼剩下的惟一一個服務器一樣將沒法處理全部的用戶請求。

  或許您會問:L3/4負載平衡服務器必定要有兩個麼?其實主要由各負載平衡服務器產品自身來決定的。在前面咱們已經講過,實際上探測負載平衡服務器的可用性實際上須要很複雜的測試邏輯。所以若是一旦咱們在一個負載平衡系統中使用了過多的L3/4負載平衡服務器,那麼這些負載平衡服務器之間所發送的各類心跳測試將消耗很是多的資源。同時因爲不少L3/4負載平衡服務器自己是基於硬件的,所以它可以很是快速地工做,甚至能夠達到與其所支持的網絡帶寬所匹配的處理能力。所以在通常狀況下,L3/4負載平衡服務器是成對使用的。

  若是L3/4負載平衡服務器真的接近其負載極限,那麼咱們還能夠經過DNS負載平衡來分散請求:

  這種方法不只僅能夠解決擴展性的問題,更能夠利用DNS的一個特性來提升用戶體驗:DNS能夠根據用戶所在的區域選擇距離用戶最近的服務器。這在一個全球性的服務中尤其有效。畢竟一箇中國用戶訪問在中國架設的服務實例要比訪問在美國架設的服務實例快得多。

  反過來因爲L7負載平衡服務器主要是基於軟件的,所以不少L7負載平衡服務器容許用戶建立較爲複雜的負載平衡服務器系統。例如定義一個具備兩個啓用而有一個備用的一組L7負載平衡服務器。

  講解完了高可用性,咱們就來介紹一下負載平衡服務器的擴展性。其實在上面咱們剛剛介紹過,L3/4負載平衡服務器擁有很高的性能,所以通常的服務所使用的負載平衡系統不會遇到須要擴展性的問題。可是一旦出現了須要擴展的狀況,那麼使用DNS負載平衡就能夠達到較好的擴展性。而L7負載平衡則更爲靈活,所以擴展性更不是問題。

  可是一個負載平衡系統不可能都是由L3/4負載平衡服務器組成的,也不可能只由L7負載平衡服務器組成的。這是由於二者在性能和價格上都具備很是大的差別。一個L3/4負載平衡服務器實際上價格很是昂貴,經常達到上萬美圓。而L7負載平衡服務器則可使用廉價服務器搭建。L3/4負載平衡服務器經常具備很是高的性能,而L7負載平衡服務器則經常經過組成一個集羣來達到較高的總體性能。

  在設計負載平衡系統時,還有一點須要考慮的那就是服務的動靜分離。咱們知道,一個服務經常由動態請求和靜態請求共同組成。這兩種請求具備很是不一樣的特色:一個動態請求經常須要大量的計算而傳輸的數據經常不是不少,而一個靜態的請求經常須要傳輸大量的數據而不須要太多的計算。不一樣的服務容器對這些請求的表現差別很大。所以不少服務經常將其所包含的服務實例分爲兩部分,分別用來處理靜態請求和動態請求,並使用適合的服務容器提供服務。在這種狀況下,靜態請求經常被置於特定的路徑下,如「/static」。這樣負載平衡服務器就能夠根據請求所發送到的路徑而將動態請求和靜態請求進行適當地轉發。

  最後要提到的就是L3/4負載平衡服務器的一個軟件實現LVS(Linux Virtual Server)。相較於硬件實現,軟件實現須要作不少額外的工做,例如對數據包的解碼,爲處理數據包分配內存等等呢個。所以其性能經常只是具備相同硬件能力的L3/4負載平衡服務器的1/5到1/10。鑑於其只具備有限的性能可是搭建起來成本很低,如利用已有的在Lab裏閒置的機器等,所以其經常在服務規模不是很大的時候做爲臨時替代方案使用。

 

負載平衡解決方案

  在文章的最後,咱們將給出一系列常見的負載平衡解決方案,以供你們參考。

  在通常狀況下,一個服務的負載經常是經過某些方式逐漸增加的。相應地,這些服務所擁有的負載平衡系統經常是從小到大逐漸演化的。所以咱們也將會按照從小到大的方式逐次介紹這些負載平衡系統。

  首先是最簡單的包含一對L7負載平衡服務器的系統:

  若是服務的負載逐漸增大,那麼該系統中惟一的L7負載平衡服務器很容易變成瓶頸。此時咱們能夠經過添加一個SSL Farm以及運行LVS的服務器來解決問題:

  若是咱們還要應對增加的負載,那麼就須要使用真正的基於硬件的L3/4負載平衡服務器來替代LVS,並增長各層的容量:

  因爲該解決方案的下面三層基本都有理論上無限的擴展性,所以最容易出現過載的就是最上面的L3/4負載平衡服務器。在這種狀況下,咱們就須要使用DNS來分配負載了:

 

轉載請註明原文地址並標明轉載:http://www.cnblogs.com/loveis715/p/4547968.html

商業轉載請事先與我聯繫:silverfox715@sina.com

相關文章
相關標籤/搜索