天天看點

基于多線程的大容量MMORPG主邏輯伺服器實作政策

轉載請标明出處:http://blog.csdn.net/herm_lib/article/details/9079309

實際參與的商業項目而且已營運的伺服器,邏輯這塊都是一個獨立的單線程的,網絡跑在其他線程中。像接入伺服器,由于他自身的特點,可以盡量利用CPU,做到大負載接入。大部分商業伺服器,包括網遊伺服器,瓶頸還是在于邏輯而非網絡,是以接入伺服器這塊也沒有必要的優化。

以前總結過接入伺服器的優化的政策:遊戲網關伺服器性能優化的一種方案 http://blog.csdn.net/herm_lib/article/details/7085181

今天想到了大世界伺服器,以前出于興趣,基于多線程實作了一個邏輯伺服器,當時印象比較深刻。但随着時間的推移和年紀增長記憶力衰退,發現當時實作政策已經不再清晰。重新翻了一下以前的代碼,好好地回憶,趕快把自己的了解記錄下來。

今天的話題說得直白點就是,類似WOW這樣的遊戲,如何能做到支援最大數量的同時線上呢?這類遊戲大地圖是一個公共的開放空間,而且玩家角色之間是互相可見的,須要控制視野。實作大型戰場的話,可以考慮參考本文的方法。

今天的文章基于的前提條件

        伺服器硬體足夠強大,4CPU8核或者8CPU16核之類的。單台機器如果不夠強,采用網絡分布式的方案,理論上是不滿足高即時的邏輯要求的。

要支援最大數量的同時線上,本質上就采用分布式政策。

一種方法是将地圖分成多塊,配置設定特定的線程為某塊伺服器。這個政策基本是不可行的,因為每一塊的地圖角色數量是不均衡的。除非,從設計角度強制每一塊地圖的人數有上限,這樣就回到那種常見的小地圖,跑兩步就要傳送到另外一個地圖塊模式中去了。

我這邊采用的方法是,将不同的玩家角色配置設定給不同的線程,比如有角色R1 R2 R3, 線程 T1 T2 T3, T1跑R1邏輯,T2跑R2邏輯。。。。  線程配置設定方式,可以簡單地為R1算個hash值,然後對應到哪個線程上。

這種方式在技術實作上,存在兩個稍微麻煩一點的地方:

1. 線程互斥

2. 不同線程中的角色資料互動

第一種就是一種純技術實作方案,我們要做到的是,多線程,但無須互斥。如果多線程,還要用各種鎖,基本上玩家一多,線程一多,再多的CPU最後可能淪落到和一個CPU接近的負載。現在這個問題就歸結到如何實作多線程不加鎖了,基本上通過下面兩點搞定:

       [1] 一生産者線程一消費者線程,通過Memroy Barrie可以不用加鎖,Memory Barrier,大家搜尋吧。

       [2] 多生産者多消費者,可以轉換成[1]中的情形。

接下來說說第二個問題,角色間的資料互動,互動形式有兩種,一種是線程内的,另外一個是線程間的。同一個線程内的兩個或者多個角色資料互動,基本上是直接同步調用就行了。 線程間的有講究,發展成類似伺服器間的資料互動,從實作角度講,可以認為和伺服器間的資料互動是一樣的,要做成異步的了。

就拿線程T1中的R1要擷取T2中的R2的等級等資訊,來說事,一般我們是擷取角色基本資訊,細節步驟如下:

       [1]  T1寫 R1擷取R2基本角色資訊的請求消息(記為GET_ROLE_BASE_INFO_REQ),到 T2的線程隊列;(R1就去做其他事情了啊。。。)

       [2]  T2取到   GET_ROLE_BASE_INFO_REQ,将 R2的 基本資訊的回應消息(GET_ROLE_BASE_INFO_RES),寫到T1的線程隊列;

       [3]  T1讀到T2的回應消息,通知給R1。

過程沒有什麼特别,和我們用戶端和伺服器,或者伺服器之間的資料互動完全一樣。 為了做到線程内和線程間的統一,線程内的角色間資料互動可以和線程間的方式統一起來。

上面的實作政策,在目前硬體條件下是可行的。有興趣的兄弟可以實踐一下,真正實踐起來就有感覺了。