1. 程式人生 > >高併發解決方案之負載均衡

高併發解決方案之負載均衡

1.什麼是負載均衡?

        當一臺伺服器的效能達到極限時,我們可以使用伺服器叢集來提高網站的整體效能。那麼,在伺服器叢集中,需要有一臺伺服器充當排程者的角色,使用者的所有請求都會首先由它接收,排程者再根據每臺伺服器的負載情況將請求分配給某一臺後端伺服器去處理。

那麼在這個過程中,排程者如何合理分配任務,保證所有後端伺服器都將效能充分發揮,從而保持伺服器叢集的整體效能最優,這就是負載均衡問題。

下面詳細介紹負載均衡的四種實現方式。 

(一)HTTP重定向實現負載均衡

過程描述

        當用戶向伺服器發起請求時,請求首先被叢集排程者截獲;排程者根據某種分配策略,選擇一臺伺服器,並將選中的伺服器的IP地址封裝在HTTP響應訊息頭部的Location欄位中,並將響應訊息的狀態碼設為302,最後將這個響應訊息返回給瀏覽器。

當瀏覽器收到響應訊息後,解析Location欄位,並向該URL發起請求,然後指定的伺服器處理該使用者的請求,最後將結果返回給使用者。

在使用HTTP重定向來實現伺服器叢集負載均衡的過程中,需要一臺伺服器作為請求排程者。使用者的一項操作需要發起兩次HTTP請求,一次向排程伺服器傳送請求,獲取後端伺服器的IP,第二次向後端伺服器傳送請求,獲取處理結果。 
 

排程策略

    排程伺服器收到使用者的請求後,究竟選擇哪臺後端伺服器處理請求,這由排程伺服器所使用的排程策略決定。

  1. 隨機分配策略 
    當排程伺服器收到使用者請求後,可以隨機決定使用哪臺後端伺服器,然後將該伺服器的IP封裝在HTTP響應訊息的Location屬性中,返回給瀏覽器即可。

  2. 輪詢策略(RR) 
    排程伺服器需要維護一個值,用於記錄上次分配的後端伺服器的IP。那麼當新的請求到來時,排程者將請求依次分配給下一臺伺服器。

由於輪詢策略需要排程者維護一個值用於記錄上次分配的伺服器IP,因此需要額外的開銷;此外,由於這個值屬於互斥資源,那麼當多個請求同時到來時,為了避免執行緒的安全問題,因此需要鎖定互斥資源,從而降低了效能。而隨機分配策略不需要維護額外的值,也就不存線上程安全問題,因此效能比輪詢要高。 
 

優缺點分析

   採用HTTP重定向來實現伺服器叢集的負載均衡實現起來較為容易,邏輯比較簡單,但缺點也較為明顯。

在HTTP重定向方法中,排程伺服器只在客戶端第一次向網站發起請求的時候起作用。當排程伺服器向瀏覽器返回響應資訊後,客戶端此後的操作都基於新的URL進行的(也就是後端伺服器),此後瀏覽器就不會與排程伺服器產生關係,進而會產生如下幾個問題:

  • 由於不同使用者的訪問時間、訪問頁面深度有所不同,從而每個使用者對各自的後端伺服器所造成的壓力也不同。而排程伺服器在排程時,無法知道當前使用者將會對伺服器造成多大的壓力,因此這種方式無法實現真正意義上的負載均衡,只不過是把請求次數平均分配給每臺伺服器罷了。
  • 若分配給該使用者的後端伺服器出現故障,並且如果頁面被瀏覽器快取,那麼當用戶再次訪問網站時,請求都會發給出現故障的伺服器,從而導致訪問失敗。

 

(二)DNS負載均衡

DNS是什麼?

在瞭解DNS負載均衡之前,我們首先需要了解DNS域名解析的過程。

我們知道,資料包採用IP地址在網路中傳播,而為了方便使用者記憶,我們使用域名來訪問網站。那麼,我們通過域名訪問網站之前,首先需要將域名解析成IP地址,這個工作是由DNS完成的。也就是域名伺服器。

我們提交的請求不會直接傳送給想要訪問的網站,而是首先發給域名伺服器,它會幫我們把域名解析成IP地址並返回給我們。我們收到IP之後才會向該IP發起請求。

那麼,DNS伺服器有一個天然的優勢,如果一個域名指向了多個IP地址,那麼每次進行域名解析時,DNS只要選一個IP返回給使用者,就能夠實現伺服器叢集的負載均衡。 
 

具體做法

首先需要將我們的域名指向多個後端伺服器(將一個域名解析到多個IP上),再設定一下排程策略,那麼我們的準備工作就完成了,接下來的負載均衡就完全由DNS伺服器來實現。

當用戶向我們的域名發起請求時,DNS伺服器會自動地根據我們事先設定好的排程策略選一個合適的IP返回給使用者,使用者再向該IP發起請求。 
 

排程策略

一般DNS提供商會提供一些排程策略供我們選擇,如隨機分配、輪詢、根據請求者的地域分配離他最近的伺服器。 
 

優缺點分析

       DNS負載均衡最大的優點就是配置簡單。伺服器叢集的排程工作完全由DNS伺服器承擔,那麼我們就可以把精力放在後端伺服器上,保證他們的穩定性與吞吐量。而且完全不用擔心DNS伺服器的效能,即便是使用了輪詢策略,它的吞吐率依然卓越。

此外,DNS負載均衡具有較強了擴充套件性,你完全可以為一個域名解析較多的IP,而且不用擔心效能問題。

但是,由於把叢集排程權交給了DNS伺服器,從而我們沒辦法隨心所欲地控制排程者,沒辦法定製排程策略。

DNS伺服器也沒辦法瞭解每臺伺服器的負載情況,因此沒辦法實現真正意義上的負載均衡。它和HTTP重定向一樣,只不過把所有請求平均分配給後端伺服器罷了。

此外,當我們發現某一臺後端伺服器發生故障時,即使我們立即將該伺服器從域名解析中去除,但由於DNS伺服器會有快取,該IP仍然會在DNS中保留一段時間,那麼就會導致一部分使用者無法正常訪問網站。這是一個致命的問題!好在這個問題可以用動態DNS來解決。 
 

動態DNS

動態DNS能夠讓我們通過程式動態修改DNS伺服器中的域名解析。從而當我們的監控程式發現某臺伺服器掛了之後,能立即通知DNS將其刪掉。

綜上所述

DNS負載均衡是一種粗獷的負載均衡方法,這裡只做介紹,不推薦使用。 


 

(三)反向代理負載均衡

什麼是反向代理負載均衡?

       反向代理伺服器是一個位於實際伺服器之前的伺服器,所有向我們網站發來的請求都首先要經過反向代理伺服器,伺服器根據使用者的請求要麼直接將結果返回給使用者,要麼將請求交給後端伺服器處理,再返回給使用者。

之前我們介紹了用反向代理伺服器實現靜態頁面和常用的動態頁面的快取。接下來我們介紹反向代理伺服器更常用的功能——實現負載均衡。

我們知道,所有傳送給我們網站的請求都首先經過反向代理伺服器。那麼,反向代理伺服器就可以充當伺服器叢集的排程者,它可以根據當前後端伺服器的負載情況,將請求轉發給一臺合適的伺服器,並將處理結果返回給使用者。 

優點

  1. 隱藏後端伺服器。 
    與HTTP重定向相比,反向代理能夠隱藏後端伺服器,所有瀏覽器都不會與後端伺服器直接互動,從而能夠確保排程者的控制權,提升叢集的整體效能。
  2. 故障轉移 
    與DNS負載均衡相比,反向代理能夠更快速地移除故障結點。當監控程式發現某一後端伺服器出現故障時,能夠及時通知反向代理伺服器,並立即將其刪除。
  3. 合理分配任務 
    HTTP重定向和DNS負載均衡都無法實現真正意義上的負載均衡,也就是排程伺服器無法根據後端伺服器的實際負載情況分配任務。但反向代理伺服器支援手動設定每臺後端伺服器的權重。我們可以根據伺服器的配置設定不同的權重,權重的不同會導致被排程者選中的概率的不同。 
     

缺點

  1. 排程者壓力過大 
    由於所有的請求都先由反向代理伺服器處理,那麼當請求量超過排程伺服器的最大負載時,排程伺服器的吞吐率降低會直接降低叢集的整體效能。
  2. 制約擴充套件 
    當後端伺服器也無法滿足巨大的吞吐量時,就需要增加後端伺服器的數量,可沒辦法無限量地增加,因為會受到排程伺服器的最大吞吐量的制約。 
     

粘滯會話

反向代理伺服器會引起一個問題。若某臺後端伺服器處理了使用者的請求,並儲存了該使用者的session或儲存了快取,那麼當該使用者再次傳送請求時,無法保證該請求仍然由儲存了其Session或快取的伺服器處理,若由其他伺服器處理,先前的Session或快取就找不到了。

解決辦法1: 
可以修改反向代理伺服器的任務分配策略,以使用者IP作為標識較為合適。相同的使用者IP會交由同一臺後端伺服器處理,從而就避免了粘滯會話的問題。

解決辦法2: 
可以在Cookie中標註請求的伺服器ID,當再次提交請求時,排程者將該請求分配給Cookie中標註的伺服器處理即可。

 

 

2.負載均衡元件

 

 

1.1、apache
     —— 它是Apache軟體基金會的一個開放原始碼的跨平臺的網頁伺服器,屬於老牌的web伺服器了,支援基於Ip或者域名的虛擬主機,支援代理伺服器,支援安全Socket層(SSL)等等,目前網際網路主要使用它做靜態資源伺服器,也可以做代理伺服器轉發請求(如:圖片鏈等),結合tomcat等servlet容器處理jsp。
1.2、ngnix
     —— 俄羅斯人開發的一個高效能的 HTTP和反向代理伺服器。由於Nginx 超越 Apache 的高效能和穩定性,使得國內使用 Nginx 作為 Web 伺服器的網站也越來越多,其中包括新浪部落格、新浪播客、網易新聞、騰訊網、搜狐部落格等入口網站頻道等,在3w以上的高併發環境下,ngnix處理能力相當於apache的10倍。
     參考:apache和tomcat的效能分析和對比(http://blog.s135.com/nginx_php_v6/)
1.3、lvs
     —— Linux Virtual Server的簡寫,意即Linux虛擬伺服器,是一個虛擬的伺服器集群系統。由畢業於國防科技大學的章文嵩博士於1998年5月創立,可以實現LINUX平臺下的簡單負載均衡。瞭解更多,訪問官網:http://zh.linuxvirtualserver.org/。

1.4、HAProxy

     —— HAProxy提供高可用性、負載均衡以及基於TCP和HTTP應用的代理,支援虛擬主機,它是免費、快速並且可靠的一種解決方案。HAProxy特別適用於那些負載特大的web站點, 這些站點通常又需要會話保持或七層處理。HAProxy執行在當前的硬體上,完全可以支援數以萬計的併發連線。並且它的執行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web伺服器不被暴露到網路上.
1.5、keepalived
     —— 這裡說的keepalived不是apache或者tomcat等某個元件上的屬性欄位,它也是一個元件,可以實現web伺服器的高可用(HA high availably)。它可以檢測web伺服器的工作狀態,如果該伺服器出現故障被檢測到,將其剔除伺服器群中,直至正常工作後,keepalive會自動檢測到並加入到伺服器群裡面。實現主備伺服器發生故障時ip瞬時無縫交接。它是LVS叢集節點健康檢測的一個使用者空間守護程序,也是LVS的引導故障轉移模組(director failover)。Keepalived守護程序可以檢查LVS池的狀態。如果LVS伺服器池當中的某一個伺服器宕機了。keepalived會通過一 個setsockopt呼叫通知核心將這個節點從LVS拓撲圖中移除。
1.6、memcached
     —— 它是一個高效能分散式記憶體物件快取系統。當初是Danga Interactive為了LiveJournal快速發展開發的系統,用於對業務查詢資料快取,減輕資料庫的負載。其守護程序(daemon)是用C寫的,但是客戶端支援幾乎所有語言(客戶端基本上有3種版本[memcache client for java;spymemcached;xMecache]),服務端和客戶端通過簡單的協議通訊;在memcached裡面快取的資料必須序列化。
1.7、terracotta
     —— 是一款由美國Terracotta公司開發的著名開源Java叢集平臺。它在JVM與Java應用之間實現了一個專門處理叢集功能的抽象層,允許使用者在不改變系統程式碼的情況下實現java應用的叢集。支援資料的持久化、session的複製以及高可用(HA)。