服務器負載均衡技術

背景介紹:

由於網絡的數據流量多集中在中心服務器一端,所以現在所說的負載均衡,多指的是對訪問服務器的負載進行均衡(或者說分擔)措施。負載均衡,從結構上分爲本 地負載均衡和地域負載均衡(全局負載均衡),前一種是指對本地的服務器集羣做負載均衡,後一種是指對分別放置在不同的地理位置、在不同的網絡及服務器羣集 之間作負載均衡。

每個主機運行一個所需服務器程序的獨立拷貝,諸如Web、FTP、Telnet或e-mail服務器程序。對於 某些服務(如運行在Web服務器上的那些服務)而言,程序的一個拷貝運行在羣集內所有的主機上,而網絡負載均衡則將工作負載在這些主機間進行分配。對於其他服務(例如e-mail),只有一臺主機處理工作負載,針對這些服務,網絡負載均衡允許網絡通訊量流到一個主機上,並在該主機發生故障時將通訊量移至其他主機。

常見服務器負載均衡策略

1、 DNS

最早的負載均衡技術是通過DNS來實現的,在DNS中爲多個地址配置同一個名字,因而查詢這個名字的客戶機將得到其中一個地址,從而使得不同的客戶訪問不同的服務器,達到負載均衡的目的。

DNS負載均衡是一種簡單而有效的方法,但是它不能區分服務器的差異,也不能反映服務器的當前運行狀態。當使用DNS負載均衡的時候,必須儘量保證不同 的客戶計算機能均勻獲得不同的地址。由於DNS數據具備刷新時間標誌,一旦超過這個時間限制,其他DNS服務器就需要和這個服務器交互,以重新獲得地址數據,就有可能獲得不同IP地址。因此爲了使地址能隨機分配,就應使刷新時間儘量短,不同地方的DNS服務器能更新對應的地址,達到隨機獲得地址,然而將過期時間設置得過短,將使DNS流量大增,而造成額外的網絡問題。DNS負載均衡的另一個問題是,一旦某個服務器出現故障,即使及時修改了DNS設置,還是要等待足夠的時間(刷新時間)才能發揮作用,在此期間,保存了故障服務器地址的客戶計算機將不能正常訪問服務器。

儘管存在多種問題,但它還是一種非常有效的做法,包括Yahoo在內的很多大型網站都使用DNS。

也可以在客戶端實現,客戶端獲取某個域名對應的ip地址列表,然後分別去ping這些ip地址,選擇一個響應最快作爲連接服務器。這種方法可以防止某個機器故障不能及時發現的問題,響應的延遲大小也基本上可以反映網絡和服務器負載情況。這種策略的缺點是增加了客戶端代碼的複雜度。這種策略在一些升級服務器上有應用。

2、 代理服務器

使用代理服務器,可以將請求轉發給內部的服務器,使用這種加速模式顯然可以提升靜態網頁的訪問速度。然而,也可以考慮這樣一種技術,使用代理服務器將請求均勻轉發給多臺服務器,從而達到負載均衡的目的。

這種代理方式與普通的代理方式有所不同,標準代理方式是客戶使用代理訪問多個外部服務器,而這種代理方式是代理多個客戶訪問內部服務器,因此也被稱爲反向代理模式。雖然實現這個任務並不算是特別複雜,然而由於要求特別高的效率,實現起來並不簡單。

使用反向代理的好處是,可以將負載均衡和代理服務器的高速緩存技術結合在一起,提供有益的性能。然而它本身也存在一些問題,首先就是必須爲每一種服務都專門開發一個反向代理服務器,這就不是一個輕鬆的任務。

代理服務器本身雖然可以達到很高效率,但是針對每一次代理,代理服務器就必須維護兩個連接,一個對外的連接,一個對內的連接,因此對於特別高的連接請求,代理服務器的負載也就非常之大。反向代理方式下能應用優化的負載均衡策略,每次訪問最空閒的內部服務器來提供服務。但是隨着併發連接數量的增加,代理服務器本身的負載也變得非常大,最後反向代理服務器本身會成爲服務的瓶頸。

3、 地址轉換網關

支持負載均衡的地址轉換網關,可以將一個外部IP地址映射爲多個內部IP地址,對每次TCP連接請求動態使用其中一個內部地址,達到負載均衡的目的。很多 硬件廠商將這種技術集成在他們的交換機中,作爲他們第四層交換的一種功能來實現,一般採用隨機選擇、根據服務器的連接數量或者響應時間進行選擇的負載均衡 策略來分配負載。由於地址轉換相對來講比較接近網絡的低層,因此就有可能將它集成在硬件設備中,通常這樣的硬件設備是局域網交換機。

當前局域網交換機所謂的第四層交換技術,就是按照IP地址和TCP端口進行虛擬連接的交換,直接將數據包發送到目的計算機的相應端口。通過交換機就能將 來自外部的初始連接請求,分別與內部的多個地址相聯繫,此後就能對這些已經建立的虛擬連接進行交換。因此,一些具備第四層交換能力的局域網交換機,就能作 爲一個硬件負載均衡器,完成服務器的負載均衡。

由於第四層交換基於硬件芯片,因此其性能非常優秀,尤其是對於網絡傳輸速度和交換 速度遠遠超過普通的數據包轉發。然而,正因爲它是使用硬件實現的,因此也不夠靈活,僅僅能夠處理幾種最標準的應用協議的負載均衡,如HTTP 。當前負載均衡主要用於解決服務器的處理能力不足的問題,因此並不能充分發揮交換機帶來的高網絡帶寬的優點。

4、 協議內部支持

除了這三種負載均衡方式之外,有的協議內部支持與負載均衡相關的功能,例如HTTP協議中的重定向能力等,HTTP運行於TCP連接的最高層。客戶端通過 端口號80的TCP服務直接連接到服務器,然後通過TCP連接向服務器端發送一個HTTP請求。在服務器分清客戶端所需的網頁和資源之前,至少要進行四次 TCP的數據包交換請求。由於負載平衡設備要把進入的請求分配給多個服務器,因此,它只能在TCP連接時建立,且HTTP請求通過後才能確定如何進行負載 的平衡。當一個網站的點擊率達到每秒上百甚至上千次時,TCP連接、HTTP報頭信息以及進程的時延已經變得很重要了。在HTTP請求和報頭中有很多對負 載平衡有用的信息。首先,也是最重要的一點是,我們可以從這些信息中獲知客戶端所請求的URL和網頁,利用這個信息,負載平衡設備就可以將所有的圖像請求 引導到一個圖像服務器,或者根據URL的數據庫查詢內容調用CGI程序,將請求引導到一個專用的高性能數據庫服務器。惟一能侷限這些信息獲取的因素是負載 平衡設備本身的靈活程度。事實上,如果網絡管理員熟悉Web內容交換技術,他可以僅僅根據HTTP報頭的cookie字段來使用Web內容交換技術改善對 特定客戶的服務,如果能從HTTP請求中找到一些規律,還可以充分利用它作出各種決策。除了TCP連接表的問題外,如何查找合適的HTTP報頭信息以及作 出負載平衡決策的過程,是影響Web內容交換技術性能的重要問題。

但它依賴於特定協議,因此使用範圍有限。根據現有的這些負載均衡技術,並應用優化的均衡策略,來實現後端服務器負載分擔的最優狀態。

遊戲世界的負載均衡

1、 根據功能模塊分散壓力

每個服務器只完成特定功能,玩家根據需要連接不同的服務器。

clip_image002

2、 根據玩家數目分散壓力

每個服務器完成所有功能,把玩家分配到不同服務器中,從而減少單個服務器壓力。

clip_image004

BigWorld介紹

1、本地交互是廉價的,跨主機交互是昂貴的,因此儘量把相互接近的實體放到同一個服務器上。

地理上相差很遠的實體則考慮放到不同服務器上。

clip_image006

3、 以實體(玩家、怪物和其他NPC等)爲中心計算負載

實體作爲單一事件的代碼和數據。

實體可以在不同主機間移動。

實體都可以被保存到數據庫。

clip_image008

4、 地圖的劃分有靜態的和動態兩種。

靜態劃分雖然容易,但是很多時候並不能反映真實的負載情況。

動態劃分雖然開發難度大些,但是更靈活,更容易平衡真實負載。

動態劃分是通過實時的移動不同遊戲服務器的地圖邊界來實現的。

動態劃分可以實時調整不同服務器的壓力,無需預先配置和預測。

clip_image010

5、 如何提高效率

減少服務器之間的交互。

在邊界區域放置實體對象的拷貝(ghost對象)。

所有讀操作都在本地執行,這樣比遠程讀取對象屬性快很多。

假設一個地圖由6個server來負責

clip_image012

以server 5爲例

clip_image014

其中綠色區域是用來放置臨近的其他server的ghost對象

 
  clip_image016

其中綠色區域爲發送實體對象信息到其他臨近server用來創建ghost對象

clip_image018

如何減少不同主機之間的通信

1、 通過RPC調用改變對象狀態屬性。

2、 所有的讀操作都在本地執行。

3、 寫操作會從ghost對象傳到實體對象。

a) print localMonster.health

i. Reads from local copy

b) localMonster.attack()

i. Calls “attack” function directly on local object

c) print remoteMonster.health

i. Reads from local ghost copy

d) remoteMonster.attack()

i. Sends command to remote server

ii. Remote server calls “attack” on local object

通過AOI來提高數據通知效率

1、 最簡單的方法是所有對象互相可見。

2、 這樣會導致n2 次數據傳遞,代價非常大。

3、 如果只是發給對象感興趣的區域(Area of Interest , AOI ),則可以大大提高通知效率。

下面是AOI示意圖

clip_image020

問題與解決方案

問題一

實體對象在不同server間移動,但是由於server的ip是動態變化,讓客戶端來做又不合適,一個合理的做法是加入代理服務器proxy。

最簡單的架構

clip_image022

使用代理服務器(BaseApp)

clip_image024

使用代理服務器轉發報文

用戶在CellApp 1上

clip_image026

用戶移動到CellApp 2上

clip_image028

問題二

當對象給另外一個服務器的對象發送消息或RPC,在回覆消息之前被負載均衡方式移動到其他服務器,這時回覆消息是否會出錯?

使用郵箱和自動轉發功能解決這個問題。

在下面的例子中,player 2隨便在那個服務器上,當他向player 1發送一條消息後被轉移到其他服務器,但是他還是能夠收到player 1的回覆。

clip_image029

服務器伸縮性演示

播放影片

問題三

硬件和實體都可能不是統一的,硬件有差別,不同實體的開銷也不相同。

解決方法:根據cpu的消耗情況來分擔負載,而不是根據用戶數目。

如何處理當機

1、 所有機器都向中心服務器彙報狀態。

2、 當機發生時,不同遊戲服務器的地圖邊界重新劃分。

3、 負載重新分配。

4、 死亡的對象通過ghost恢復,由於重疊的區域比較大,因此真正死亡的對象不多。

如何防止還未死掉的機器過載

1、 減少加載的對象數目。

2、 減少工作負載直到條件改善。

一個負載均衡之後的示例

clip_image031

物理地圖的單元劃分

整個世界地圖被劃分成很多單元,每一個單元都是100×100平方米的面積,負載均衡時邊界調整是以單元爲單位的。

單元的劃分也有利於並行加載地圖,提高了加載的速度。

當一個地圖的容量超過機器物理內存時,也可以輕鬆處理。

理論上支持無限大的地圖。

數據庫伸縮處理

傳統的最簡單的處理是,所有的遊戲服務器都和一箇中心數據庫打交道,這樣會導致中心數據庫的壓力過大,容易出現過載。

解決方案:

每個BaseApp都有一個SQLite DB,然後SQLite DB把數據合併到中心數據庫。

這樣大大減少了中心數據庫的壓力。

如何保證對象ID唯一性

1、對象必須有唯一性ID,否則對象在不同服務器間移動就有問題。

2、如果都在中心數據庫產生唯一性ID,這樣會導致中心數據庫的壓力成爲一個瓶頸。

解決方案一:

在不同機器上隨機產生128位的ID,這樣重複的可能性很小,但是並不完美。

另外,128位對象ID顯得有點長。

解決方案二:

有中心數據庫給每個遊戲服務器分配ID,每個遊戲服務器再給本機器上的對象分配下級ID。

這樣拼接起來的ID肯定不會有重複,而且長度較短。

缺點是ID浪費較大,每個遊戲服務器都佔有一個號碼段,跟用戶多少無關。

如何處理邊緣對象的移動

由於服務器的地圖邊緣經常動態移動,那麼如何處理在地圖邊緣來回移動的對象?該對象可能在兩個不同服務器上來回移動。

這些移動對服務器的性能有較大影響。

解決方案:

1、 延遲處理,是否定時處理?

2、 一些重要的對象身份屬性不依賴於物理位置。

發佈了17 篇原創文章 · 獲贊 33 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章