1. 程式人生 > >關於遊戲架構設計的一些整理吧

關於遊戲架構設計的一些整理吧

一個大型的網落遊戲伺服器應該包含幾個模組:網路通訊,業務邏輯,資料儲存,守護監控(不是必須),其中業務邏輯可能根據具體需要,又劃分為好幾個子模組。

這裡說的模組可以指一個程序,或者一個執行緒方式存在,本質上就是一些類的封裝。

對於伺服器的併發性,要麼採用單程序多執行緒,要麼採用多程序單執行緒的方式,說說兩種方式的優缺點:

一、單程序多執行緒的伺服器設計模式,只有一個程序,但一個程序包好多個執行緒:

網路通訊層,業務邏輯,資料儲存,分別在獨立的執行緒中,無守護程序。

優點:

1.資料共享和交換方便,使用全域性變數或者單例就可以,資料儲存方便。

2.單程序,伺服器框架結構相對簡單,編碼容易。

缺點:

1.所有功能只能在單個物理伺服器上,不能做成分散式。

2.不方便監控各個執行緒狀態,容易死鎖

3.一個執行緒出錯,例如記憶體非法訪問,棧空間被破壞,那麼伺服器程序就退出,所有玩家掉線,影響大。

二、多程序單執行緒的伺服器設計模式,多個程序,每個程序只有一個執行緒:

網路通訊,業務邏輯,資料儲存,守護程序,分別在不同的程序。

優點:

1.各個程序可以分佈在不同的物理伺服器上,可以做成分散式的伺服器框架,例如可以將資料儲存單獨放到一個物理伺服器上,供幾個區的伺服器使用。將網路通訊程序獨立出來,甚至可以做成導向伺服器,實現跨服戰。

2.可以通過守護程序監控其它程序狀態,例如有程序死掉,馬上重啟該程序,或者某個程序cpu使用率接近100%(基本可以判斷是某個邏輯死迴圈了), 強制kill掉該程序,然後重啟。

3.單個伺服器程序異常退出,只要不是網路通訊程序(一般這個都會比較穩定,沒什麼邏輯),那麼就可以及時被守護程序重啟,不會造成玩家掉線,只會造成在1-2秒內,某個邏輯功能無法使用,甚至玩家都感覺不到。

4.伺服器通過共享記憶體進行資料交換,那麼如果其中一個伺服器死掉,資料還在,可以保護使用者資料(當然多執行緒也可以使用共享記憶體)。

5.併發性相對多執行緒要高點。

缺點:

1.不方便使用互斥鎖,因為程序切換的時間片遠遠於執行緒切換,對於一個高併發伺服器是無法允許這麼高時間片的切換代價的。因此必須設計好伺服器的框架,儘量避開使用鎖機制,但要保證資料不出錯。

2.多程序程式設計,在各個程序間會有很多通訊,跨伺服器程序的非同步訊息較多,會讓伺服器的編碼難度加大。

下面先按照一個遊戲的功能,將伺服器的功能分塊框架畫出來:


以上是一個遊戲伺服器最基礎的功能框架圖,接下來要做的就是設計伺服器的框架了



1.    早期的MMORPG伺服器結構

Client<->GameServer<->DB    所有業務,資料集中處理

優點:簡單,快速開發
缺點:
    1.所有業務放在一起,系統負擔大大增加.一個bug可能導致整個伺服器崩潰,造成所有玩家掉線甚至丟失等嚴重後果。
    2.開服一剎那,所有玩家全部堆積在同一個新手村.->>>>卡,客戶端卡(同屏人數過多渲染/廣播風暴) 伺服器卡(處理大量同場景訊息/廣播風暴)
2.    中期-使用者分離叢集式

                GameServe1
Client            |                    DB
                GameServer2

玩家不斷增多->分線->程式自動或玩家手動選擇進入
缺點:運營到後期,隨著每條線玩家的減少, 互動大大減少。

3.    中後期 資料分離叢集式 按地圖劃分伺服器,當前主流
    新手村問題:《天龍八部》提出了較好的解決方案,建立多個平行的新手村地圖,一主多副,開服時儘可能多的同時容納新使用者的湧入,高等級玩家從其它地圖回新手村只能到達主新手村。

4.    當前主流的網路遊戲架構


        注:在GateServer和CenterServer之間是有一條TCP連線的。而GameServer和LogServer之間的連線可以是UDP連線。這是有一個大概的圖,很多地方需要細化。
GateServer:閘道器伺服器,AgentServer、ProxyServer

 優點
    (1)作為網路通訊的中轉站,負責維護將內網和外網隔離開,使外部無法直接訪問內部伺服器,保障內網伺服器的安全,一定程度上較少外掛的攻擊。
    (2)閘道器伺服器負責解析資料包、加解密、超時處理和一定邏輯處理,這樣可以提前過濾掉錯誤包和非法資料包。
    (3)客戶端程式只需建立與閘道器伺服器的連線即可進入遊戲,無需與其它遊戲伺服器同時建立多條連線,節省了客戶端和伺服器程式的網路資源開銷。
    (4)在玩家跳伺服器時,不需要斷開與閘道器伺服器的連線,玩家資料在不同遊戲伺服器間的切換是內網切換,切換工作瞬問完成,玩家幾乎察覺不到,這保證了遊戲的流暢性和良好的使用者體驗。

   缺點
1.閘道器伺服器成為高負載情況下的通訊瓶頸問題
2由於閘道器的單節點故障導致整組伺服器無法對外提供服務的問題

   解決:多閘道器技術。顧名思義,“多閘道器” 就是同時存在多個閘道器伺服器,比如一組伺服器可以配置三臺GameGme。當負載較大時,可以通過增加閘道器伺服器來增加閘道器的總體通訊流量,當一臺閘道器伺服器宕機時,它只會影響連線到本伺服器的客戶端,其它客戶端不會受到任何影響。

DCServer:資料中心伺服器。主要的功能是快取玩家角色資料,保證角色資料能快速的讀取和儲存
CenterServer:全域性伺服器/中心伺服器,也叫WorldServer. 主要負責維持GameServer之間資料的轉發和資料廣播。另外一些遊戲系統也可能會放到Center上處理,比如好友系統,公會系統。

    改進:將閘道器伺服器細化為LogingateServer和多個GameGateServer.

5.    按業務分離式叢集
由於網路遊戲存在很多的業務,如聊天,戰鬥,行走,NPC等,可以將某些業務分到單獨的伺服器上。這樣每個伺服器的程式則會精簡很多。而且一些大流量業務的分離,可以有效的提高遊戲伺服器人數上限。


優點:
      1.業務的分離使得每種伺服器的程式變的簡單,這樣可以降低出錯的機率。即使出錯,也不至於影響到每一個整個遊戲的進行,而且通過快速啟動另一臺備用伺服器替換出錯的伺服器。
     2.業務的分離使得流量得到了分散,進而相應速度回得到提升 。
     3.大部分業務都分離了成了單獨的伺服器,所以可以動態的新增,從而提高人數上限。

改進:甚至可以將登陸伺服器細化拆分建角色,選擇角色伺服器
6.    一種簡單實用的網路遊戲伺服器架構

下圖中每個方框表示一個獨立的程序APP元件,每個服務程序如果發生宕機會影響部分使用者,整體服務但不會全部中斷。在宕機程序重啟後,又可以併入整體,全部服務得以繼續。



gls:game login server,遊戲登入伺服器,某種程式上,其不是核心元件,gls呼叫外部的介面,進行基本的使用者名稱密碼認證。此外需要實現很多附屬的功能:登入排隊 (對開服非常有幫助),GM超級登入通道(GM可以不排隊進入遊戲),封測期間啟用使用者控制,限制使用者登入,控制客戶端版本等。
db:實質上是後臺sql的大記憶體緩衝,隔離了資料庫操作,比較記憶體中的資料,只把改變的資料定時批量寫入sql。系統的演算法,開發穩定性都要求非常高。
center:所有元件都要在這裡註冊,線上玩家的session狀態都在這裡集中存放,和各元件有心跳連線。所有對外的介面也全部通過這裡。
角色入口:玩家登入遊戲後的選擇角色
gs:game server,最核心元件,同一地圖,所有遊戲邏輯相關的功能,都在這裡完成。
gate:建立和使用者的常連結,主要作sockt轉發,遮蔽惡意包,對gs進行保護。協議加密解密功能,一個gate共享多個gs,降低跳轉地圖連線不上的風險。
IM,關係,寄售:表示其它元件,負責對應的跨地圖發生全域性的遊戲邏輯。

7.另一個架構圖

    1-   這是一條WebService的管道,在使用者啟用該區帳號,或者修改帳號密碼的時候,通過這條通道來插入和更新使用者的帳號資訊。
    2-   這也是一條WebService管道,用來獲取和控制使用者該該組內的角色資訊,以及進行付費商城代幣之類的更新操作。
    3-   這是一條本地的TCP/IP連線,這條連線主要用來進行伺服器組在登陸伺服器的註冊,以及登陸伺服器驗證帳戶後,向用戶伺服器註冊帳戶登陸資訊,以及進行對已經登陸的帳戶角色資訊進行操作(比如踢掉當前登陸的角色),還有伺服器組的資訊更新(當前線上玩家數量等)。
    4-   這也是一條本地TCP/IP連線,這條連線用來對連線到GameServer的客戶端進行驗證,以及獲取角色資料資訊,還有傳回GameServer上角色的資料資訊改變。
    5-   這條連線也是一條本地的TCP/IP連線,它用來進行公共資訊伺服器和數個遊戲伺服器間的互動,用來交換一些遊戲世界級的資訊(比如公會資訊,跨服組隊資訊,跨服聊天頻道等)。
    6-   這裡的兩條連線,想表達的意思是,UserServer和GameServer的Agent是可以互換使用的,也就是玩家進入組內之後,就不需要再切換 Agent。如果不怕亂套,也可以把登陸伺服器的Agent也算上,這樣使用者整個過程裡就不需要再更換Agent,減少重複連線的次數,也提高了穩定性。 (畢竟連線次數少了,也降低了連不上伺服器的出現機率)
在這個架構裡面,GameServer實際上是一個遊戲邏輯的綜合體,裡面可以再去擴充套件成幾個不同的邏輯伺服器,通過PublicServer進行公共資料交換。
    UserServer實 際上扮演了一個ServerGroup的領頭羊的角色,它負責向LoginServer註冊和更新伺服器組的資訊(名字,當前人數),並且對Agent進 行排程,對選擇了該組的玩家提供一個使用者量最少的Agent。同時,它也兼了一個角色管理伺服器的功能,傳送給客戶端當前的角色列表,角色的建立,刪除, 選擇等管理操作,都是在這裡進行的。而且,它還是一個使用者資訊的驗證伺服器,GameServer需要通過它來進行客戶端的合法性驗證,以及獲取玩家選擇 的角色資料資訊。
採用這種架構的遊戲,通常有以下表現。
    1- 使用者必須啟用一個大區,才能在大區內登陸自己的帳號。
    2- 使用者啟動客戶端的時候,彈出一個登陸器,選擇大區。
    3- 使用者啟動真正的客戶端的時候,一開始就是輸入帳號密碼。
    4- 帳號驗證完成之後,進行區內的伺服器選擇。
    5- 伺服器選擇完成之後,進入角色管理。同時,角色在不同的伺服器裡不能共享。
四.正文網路通訊

1.網路協議
 根據遊戲型別    實時性要求/是否允許丟包 來決定 TCP/UDP協議

a.TCP:面向連線,可靠,保證順序,慢,有延遲
     TCP每次傳送一個數據包後都要等待接收方傳送一個應答資訊,這樣TCP才可以確認資料包通過因特網完整地送到了接收方。如果在一段時間內TCP沒有收到 接收方的應答,他就會停止傳送新的資料包,轉而去重新發送沒有收到應答2的資料包,並且持續這種傳送狀態知道收到接收方的應答。所以這會造成網路資料傳輸 的延遲,若網路情況不好,傳送方會等待相當長一段時間
       UDP:無連線,不可靠,不保證順序,快

b.長連線/短連線
長連線,指在一個TCP連線上可以連續傳送多個數據包,在TCP連線保持期間,如果沒有資料包傳送,需要雙方發檢測包以維持此連線,一般需要自己做線上維
    連線→資料傳輸→保持連線(心跳)→資料傳輸→保持連線(心跳)→……→關閉連線
短連線是指通訊雙方有資料互動時,就建立一個TCP連線,資料傳送完成後,則斷開此TCP連線,如Http
    連線→資料傳輸→關閉連線
2.IO模型

       Unix5中io模型
1.    阻塞IO (Blocking I/O Model)
2.    非阻塞IO (Nonblocking I/O Model)
3.    IO複用 (I/O Multiplexing Model)
4.    訊號驅動IO (Signal-Driven I/O Model)
5.    非同步IO (Asynchronous I/O Model)

IO分兩個階段:
1.通知核心準備資料。2.資料從核心緩衝區拷貝到應用緩衝區

根據這2點IO型別可以分成:
    1.阻塞IO,在兩個階段上面都是阻塞的。
    2.非阻塞IO,在第1階段,程式不斷的輪詢直到資料準備好,第2階段還是阻塞的
    3.IO複用,在第1階段,當一個或者多個IO準備就緒時,通知程式,第2階段還是阻塞的,在第1階段還是輪詢實現的,只是所有的IO都集中在一個地方,這個地方進行輪詢
    4.訊號IO,當資料準備完畢的時候,訊號通知程式資料準備完畢,第2階段阻塞
    5.非同步IO,1,2都不阻塞







   
同時阻塞多個I/O操作。而且可以同時對多個讀操作,多個寫操作的I/O函式進行檢測,直到有資料可讀或可寫時,才真正呼叫I/O操作函式
Java#Selector

允許套介面進行訊號驅動I/O,並安裝一個訊號處理函式,程序繼續執行並不阻塞。當資料準備好時,程序會收到一個SIGIO訊號,可以在訊號處理函式中呼叫I/O操作函式處理資料.

Java#NIO2
發出系統呼叫後,直接返回。通知IO操作完成。
前四種同步IO,最後一種非同步IO.二者區別:第二個階段必須要求程序主動呼叫recvfrom.而非同步io則將io操作全部交給核心完成,完成後發訊號通知。此期間,使用者不需要去檢查IO操作的狀態,也不需要主動的去拷貝資料。

3.執行緒阻塞的原因:

    1.Thread.sleep(),執行緒放棄CPU,睡眠N秒,然後恢復執行
    2.執行緒要執行一段同步程式碼,由於無法獲得相關的鎖,阻塞。獲得同步鎖後,才可以恢復執行。
    .執行緒執行了一個物件的wait方法,進入阻塞狀態,只有等到其他執行緒執行了該物件的notify、nnotifyAll,才能將其喚醒。
    4.IO操作,等待相關資源
阻塞執行緒的共同特點是:放棄CPU,停止執行,只有等到導致阻塞的原因消除,才能恢復執行 。或者被其他執行緒中斷,該執行緒會退出阻塞狀態,並丟擲InterruptedException.

4.
阻塞/非阻塞/同步/非同步
同步/非同步關注的是訊息如何通知的機制。而阻塞和非阻塞關注的是處理訊息。是兩組完全不同的概念。

5.幾個常用概念
Select Poll
Epoll(Linux) Kqueue(FreeBSD)   
IOCP    windows  
Reactor
Dispatcher(分 發器),Notifer(通知器), 事件到來時,使用Dispatcher(分發器)對Handler進行分派,這個Dispatcher要對所有註冊的Handler進行維護。同時,有一 個Demultiplexer(分揀器)對多路的同步事件進行分揀。    

Proactor
Proactor和Reactor都是併發程式設計中的設計模式.用於派發/分離IO操作事件的。這裡所謂的IO事件也就是諸如read/write的IO操作。"派發/分離"就是將單獨的IO事件通知到上層模組。兩個模式不同的地方在於,Proactor用於非同步IO,而Reactor用於同步IO。

兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模組,這個IO操作可以進行或已經完成)。在結構上,兩者也有相同點:demultiplexor負責提交IO操作(非同步)、查詢裝置是否可操作(同步),然後當條件滿足時,就回調handler。
不同點在於,非同步情況下(Proactor),當回撥handler時,表示IO操作已經完成;同步情況下(Reactor),回撥handler時,表示IO裝置可以進行某個操作(can read or can write),handler這個時候開始提交操作。

6.
網路通訊框架
TCP Server框架:
Apache MINA(Multipurpose Infrastructure for Network Applications)2.0.4
Netty 3.5.0Final
Grizzly 2.2
Quickserver是一個免費的開源Java庫,用於快速建立健壯的多執行緒、多客戶端TCP伺服器應用程式。使用QuickServer,使用者可以只集中處理應用程式的邏輯/協議
Cindy 強壯,可擴充套件,高效的非同步I/O框架
xSocket一個輕量級的基於nio的伺服器框架用於開發高效能、可擴充套件、多執行緒的伺服器。該框架封裝了執行緒處理、非同步讀/寫等方面
ACE 6.1.0 C++ADAPTIVE CommunicationEnvironment,
SmaxFoxServer 2.X 專門為Adobe Flash設計的跨平臺socket伺服器

7.訊息編碼協議
AMF/JSON/XML/自定義/ProtocolBuffer

無論是做何種網路應用,必須要解決的問題之一就是應用層從位元組流中拆分出訊息的問題,也就是對於 TCP 這種位元組流協議,接收方應用層能夠從位元組流中識別傳送方傳輸的訊息.
1.使用特殊字元或者字串作為訊息的邊界,應用層解析收到的位元組流時,遇見此字元或者字串則認為收到一個完整的訊息 
2.為每個訊息定義一個長度,應用層收到指定長度的位元組流則認為收到了一個完整的訊息
訊息分隔標識(separator)、訊息頭(header)、訊息體(body)
 len | message_id | data 

 |separator |     header   | body |
 | len       | message_id | data

8. 粘包:
TCP粘包是指傳送方傳送的若干包資料到接收方接收時粘成一包,從接收緩衝區看,後一包資料的頭緊接著前一包資料的尾。 
    1.傳送方引起的粘包是由TCP協議本身造成的,TCP為提高傳輸效率,傳送方往往要收集到足夠多的資料後才傳送一包資料。若連續傳送幾次的資料都很少,通常TCP會根據優化演算法把這些資料合成一包後一次傳送出去,這樣接收方就收到了粘包資料。
    2. 接收方引起的粘包是由於接收方使用者程序不及時接收資料,從而導致粘包現象。這是因為接收方先把收到的資料放在系統接收緩衝區,使用者程序從該緩衝區取資料, 若下一包資料到達時前一包資料尚未被使用者程序取走,則下一包資料放到系統接收緩衝區時就接到前一包資料之後,而使用者程序根據預先設定的緩衝區大小從系統接 收緩衝區取資料,這樣就一次取到了多包資料

解決措施:
    1.對於傳送方引起的粘包現象,使用者可通過程式設計設定來避免,TCP提供了強制資料立即傳送的操作指令push,TCP軟體接收到該操作指令後,就立即將本段資料傳送出去,而不必等待發送緩衝區滿;
TCP-NO-DELAY-關閉了優化演算法,不推薦
    2.對於接收方引起的粘包,則可通過優化程式設計、精簡接收程序工作量、提高接收程序優先順序等措施,使其及時接收資料,從而儘量避免出現粘包現象-當傳送頻率高時依然可能出現粘包
    3.接收方控制,將一包資料按結構欄位,人為控制分多次接收,然後合併,通過這種手段來避免粘包。-效率低
    4.接收方建立一預處理執行緒,對接收到的資料包進行預處理,將粘連的包分開

分包演算法思路:
基本思路是首先將待處理的接收資料(長度設為m)強行轉換成預定的結構資料形式,並從中取出資料結構長度欄位,即n,而後根據n計算得到第一包資料長度
1) 若n<m,則表明資料流包含多包資料,從其頭部擷取n個位元組存入臨時緩衝區,剩餘部分資料一次繼續迴圈處理,直至結束。
2) 若n=m,則表明資料流內容恰好是一完整結構資料,直接將其存入臨時緩衝區即可。
3) 若n>m,則表明資料流內容尚不夠構成一個完整結構資料,需留待與下一包資料合併後再行處理。

在單位設計上必須衝頭到尾貫徹面向物件的“繼承”觀念

先設計基礎單位A ,再在之上擴充套件到所有的單位,
也就是說,所有的普通單位都可以追溯到一個起源的物件,
否則程式碼量會讓你想死
然後就能獲得所有的單位和建築物了
-----------------------------------------------------------------------
地圖尋路

尋路的問題在於自然的移動,追著一個單位打,或者進入射程中停下來,比起如何自然的經過一個單位打,成為了一個,為什麼你要在A站或者B站坐公交的問題,Why,如何才能符合邏輯的設計---敵人進攻的單位,這個AI,不但是策略的問題,還是行為的問題,所以,將敵人的最終目標確定在哪裡呢?

回答:AI 和 行為控制模組要分成兩個模組來做

----------------------------------------------------------------------
行為控制模組複製地圖上所有單位的移動、攻擊等動作,目標、目的的指示;
這必須是一個獨立的模組,可以避免為每個單位都寫邏輯的同時,讓大部分單位戰鬥起來有個統一的目的;這麼做的好處是,大部分的CPU時間都在一段高效率的程式碼上,由這個模組負責按照順序給每個單位下達動作指令

如果有必要 還需要一個監控模組,監控單位的狀態改變
---------------------------------------------------------------------


AI ,就是上面寫過的 Why , 我要在A站乘車 還是B站乘車的邏輯,我是優先攻擊單位,還是優先攻擊建築物的邏輯。。。本虎還沒想明白,這是一個邏輯怪圈。。。。 1.    早期的MMORPG伺服器結構

Client<->GameServer<->DB    所有業務,資料集中處理

優點:簡單,快速開發
缺點:
    1.所有業務放在一起,系統負擔大大增加.一個bug可能導致整個伺服器崩潰,造成所有玩家掉線甚至丟失等嚴重後果。
    2.開服一剎那,所有玩家全部堆積在同一個新手村.->>>>卡,客戶端卡(同屏人數過多渲染/廣播風暴) 伺服器卡(處理大量同場景訊息/廣播風暴)
2.    中期-使用者分離叢集式

                GameServe1
Client            |                    DB
                GameServer2

玩家不斷增多->分線->程式自動或玩家手動選擇進入
缺點:運營到後期,隨著每條線玩家的減少, 互動大大減少。

3.    中後期 資料分離叢集式 按地圖劃分伺服器,當前主流
    新手村問題:《天龍八部》提出了較好的解決方案,建立多個平行的新手村地圖,一主多副,開服時儘可能多的同時容納新使用者的湧入,高等級玩家從其它地圖回新手村只能到達主新手村。

4.    當前主流的網路遊戲架構


        注:在GateServer和CenterServer之間是有一條TCP連線的。而GameServer和LogServer之間的連線可以是UDP連線。這是有一個大概的圖,很多地方需要細化。
GateServer:閘道器伺服器,AgentServer、ProxyServer

 優點
    (1)作為網路通訊的中轉站,負責維護將內網和外網隔離開,使外部無法直接訪問內部伺服器,保障內網伺服器的安全,一定程度上較少外掛的攻擊。
    (2)閘道器伺服器負責解析資料包、加解密、超時處理和一定邏輯處理,這樣可以提前過濾掉錯誤包和非法資料包。
    (3)客戶端程式只需建立與閘道器伺服器的連線即可進入遊戲,無需與其它遊戲伺服器同時建立多條連線,節省了客戶端和伺服器程式的網路資源開銷。
    (4)在玩家跳伺服器時,不需要斷開與閘道器伺服器的連線,玩家資料在不同遊戲伺服器間的切換是內網切換,切換工作瞬問完成,玩家幾乎察覺不到,這保證了遊戲的流暢性和良好的使用者體驗。

   缺點
1.閘道器伺服器成為高負載情況下的通訊瓶頸問題
2由於閘道器的單節點故障導致整組伺服器無法對外提供服務的問題

   解決:多閘道器技術。顧名思義,“多閘道器” 就是同時存在多個閘道器伺服器,比如一組伺服器可以配置三臺GameGme。當負載較大時,可以通過增加閘道器伺服器來增加閘道器的總體通訊流量,當一臺閘道器伺服器宕機時,它只會影響連線到本伺服器的客戶端,其它客戶端不會受到任何影響。

DCServer:資料中心伺服器。主要的功能是快取玩家角色資料,保證角色資料能快速的讀取和儲存
CenterServer:全域性伺服器/中心伺服器,也叫WorldServer. 主要負責維持GameServer之間資料的轉發和資料廣播。另外一些遊戲系統也可能會放到Center上處理,比如好友系統,公會系統。

    改進:將閘道器伺服器細化為LogingateServer和多個GameGateServer.

5.    按業務分離式叢集
由於網路遊戲存在很多的業務,如聊天,戰鬥,行走,NPC等,可以將某些業務分到單獨的伺服器上。這樣每個伺服器的程式則會精簡很多。而且一些大流量業務的分離,可以有效的提高遊戲伺服器人數上限。


優點:
      1.業務的分離使得每種伺服器的程式變的簡單,這樣可以降低出錯的機率。即使出錯,也不至於影響到每一個整個遊戲的進行,而且通過快速啟動另一臺備用伺服器替換出錯的伺服器。
     2.業務的分離使得流量得到了分散,進而相應速度回得到提升 。
     3.大部分業務都分離了成了單獨的伺服器,所以可以動態的新增,從而提高人數上限。

改進:甚至可以將登陸伺服器細化拆分建角色,選擇角色伺服器
6.    一種簡單實用的網路遊戲伺服器架構

下圖中每個方框表示一個獨立的程序APP元件,每個服務程序如果發生宕機會影響部分使用者,整體服務但不會全部中斷。在宕機程序重啟後,又可以併入整體,全部服務得以繼續。



gls:game login server,遊戲登入伺服器,某種程式上,其不是核心元件,gls呼叫外部的介面,進行基本的使用者名稱密碼認證。此外需要實現很多附屬的功能:登入排隊 (對開服非常有幫助),GM超級登入通道(GM可以不排隊進入遊戲),封測期間啟用使用者控制,限制使用者登入,控制客戶端版本等。
db:實質上是後臺sql的大記憶體緩衝,隔離了資料庫操作,比較記憶體中的資料,只把改變的資料定時批量寫入sql。系統的演算法,開發穩定性都要求非常高。
center:所有元件都要在這裡註冊,線上玩家的session狀態都在這裡集中存放,和各元件有心跳連線。所有對外的介面也全部通過這裡。
角色入口:玩家登入遊戲後的選擇角色
gs:game server,最核心元件,同一地圖,所有遊戲邏輯相關的功能,都在這裡完成。
gate:建立和使用者的常連結,主要作sockt轉發,遮蔽惡意包,對gs進行保護。協議加密解密功能,一個gate共享多個gs,降低跳轉地圖連線不上的風險。
IM,關係,寄售:表示其它元件,負責對應的跨地圖發生全域性的遊戲邏輯。

7.另一個架構圖

    1-   這是一條WebService的管道,在使用者啟用該區帳號,或者修改帳號密碼的時候,通過這條通道來插入和更新使用者的帳號資訊。
    2-   這也是一條WebService管道,用來獲取和控制使用者該該組內的角色資訊,以及進行付費商城代幣之類的更新操作。
    3-   這是一條本地的TCP/IP連線,這條連線主要用來進行伺服器組在登陸伺服器的註冊,以及登陸伺服器驗證帳戶後,向用戶伺服器註冊帳戶登陸資訊,以及進行對已經登陸的帳戶角色資訊進行操作(比如踢掉當前登陸的角色),還有伺服器組的資訊更新(當前線上玩家數量等)。
    4-   這也是一條本地TCP/IP連線,這條連線用來對連線到GameServer的客戶端進行驗證,以及獲取角色資料資訊,還有傳回GameServer上角色的資料資訊改變。
    5-   這條連線也是一條本地的TCP/IP連線,它用來進行公共資訊伺服器和數個遊戲伺服器間的互動,用來交換一些遊戲世界級的資訊(比如公會資訊,跨服組隊資訊,跨服聊天頻道等)。
    6-   這裡的兩條連線,想表達的意思是,UserServer和GameServer的Agent是可以互換使用的,也就是玩家進入組內之後,就不需要再切換 Agent。如果不怕亂套,也可以把登陸伺服器的Agent也算上,這樣使用者整個過程裡就不需要再更換Agent,減少重複連線的次數,也提高了穩定性。 (畢竟連線次數少了,也降低了連不上伺服器的出現機率)
在這個架構裡面,GameServer實際上是一個遊戲邏輯的綜合體,裡面可以再去擴充套件成幾個不同的邏輯伺服器,通過PublicServer進行公共資料交換。
    UserServer實 際上扮演了一個ServerGroup的領頭羊的角色,它負責向LoginServer註冊和更新伺服器組的資訊(名字,當前人數),並且對Agent進 行排程,對選擇了該組的玩家提供一個使用者量最少的Agent。同時,它也兼了一個角色管理伺服器的功能,傳送給客戶端當前的角色列表,角色的建立,刪除, 選擇等管理操作,都是在這裡進行的。而且,它還是一個使用者資訊的驗證伺服器,GameServer需要通過它來進行客戶端的合法性驗證,以及獲取玩家選擇 的角色資料資訊。
採用這種架構的遊戲,通常有以下表現。
    1- 使用者必須啟用一個大區,才能在大區內登陸自己的帳號。
    2- 使用者啟動客戶端的時候,彈出一個登陸器,選擇大區。
    3- 使用者啟動真正的客戶端的時候,一開始就是輸入帳號密碼。
    4- 帳號驗證完成之後,進行區內的伺服器選擇。
    5- 伺服器選擇完成之後,進入角色管理。同時,角色在不同的伺服器裡不能共享。
四.正文網路通訊

1.網路協議
 根據遊戲型別    實時性要求/是否允許丟包 來決定 TCP/UDP協議

a.TCP:面向連線,可靠,保證順序,慢,有延遲
     TCP每次傳送一個數據包後都要等待接收方傳送一個應答資訊,這樣TCP才可以確認資料包通過因特網完整地送到了接收方。如果在一段時間內TCP沒有收到 接收方的應答,他就會停止傳送新的資料包,轉而去重新發送沒有收到應答2的資料包,並且持續這種傳送狀態知道收到接收方的應答。所以這會造成網路資料傳輸 的延遲,若網路情況不好,傳送方會等待相當長一段時間
       UDP:無連線,不可靠,不保證順序,快

b.長連線/短連線
長連線,指在一個TCP連線上可以連續傳送多個數據包,在TCP連線保持期間,如果沒有資料包傳送,需要雙方發檢測包以維持此連線,一般需要自己做線上維
    連線→資料傳輸→保持連線(心跳)→資料傳輸→保持連線(心跳)→……→關閉連線
短連線是指通訊雙方有資料互動時,就建立一個TCP連線,資料傳送完成後,則斷開此TCP連線,如Http
    連線→資料傳輸→關閉連線
2.IO模型

       Unix5中io模型
1.    阻塞IO (Blocking I/O Model)
2.    非阻塞IO (Nonblocking I/O Model)
3.    IO複用 (I/O Multiplexing Model)
4.    訊號驅動IO (Signal-Driven I/O Model)
5.    非同步IO (Asynchronous I/O Model)

IO分兩個階段:
1.通知核心準備資料。2.資料從核心緩衝區拷貝到應用緩衝區

根據這2點IO型別可以分成:
    1.阻塞IO,在兩個階段上面都是阻塞的。
    2.非阻塞IO,在第1階段,程式不斷的輪詢直到資料準備好,第2階段還是阻塞的
    3.IO複用,在第1階段,當一個或者多個IO準備就緒時,通知程式,第2階段還是阻塞的,在第1階段還是輪詢實現的,只是所有的IO都集中在一個地方,這個地方進行輪詢
    4.訊號IO,當資料準備完畢的時候,訊號通知程式資料準備完畢,第2階段阻塞
    5.非同步IO,1,2都不阻塞







   
同時阻塞多個I/O操作。而且可以同時對多個讀操作,多個寫操作的I/O函式進行檢測,直到有資料可讀或可寫時,才真正呼叫I/O操作函式
Java#Selector

允許套介面進行訊號驅動I/O,並安裝一個訊號處理函式,程序繼續執行並不阻塞。當資料準備好時,程序會收到一個SIGIO訊號,可以在訊號處理函式中呼叫I/O操作函式處理資料.

Java#NIO2
發出系統呼叫後,直接返回。通知IO操作完成。
前四種同步IO,最後一種非同步IO.二者區別:第二個階段必須要求程序主動呼叫recvfrom.而非同步io則將io操作全部交給核心完成,完成後發訊號通知。此期間,使用者不需要去檢查IO操作的狀態,也不需要主動的去拷貝資料。

3.執行緒阻塞的原因:

    1.Thread.sleep(),執行緒放棄CPU,睡眠N秒,然後恢復執行
    2.執行緒要執行一段同步程式碼,由於無法獲得相關的鎖,阻塞。獲得同步鎖後,才可以恢復執行。
    .執行緒執行了一個物件的wait方法,進入阻塞狀態,只有等到其他執行緒執行了該物件的notify、nnotifyAll,才能將其喚醒。
    4.IO操作,等待相關資源
阻塞執行緒的共同特點是:放棄CPU,停止執行,只有等到導致阻塞的原因消除,才能恢復執行 。或者被其他執行緒中斷,該執行緒會退出阻塞狀態,並丟擲InterruptedException.

4.
阻塞/非阻塞/同步/非同步
同步/非同步關注的是訊息如何通知的機制。而阻塞和非阻塞關注的是處理訊息。是兩組完全不同的概念。

5.幾個常用概念
Select Poll
Epoll(Linux) Kqueue(FreeBSD)   
IOCP    windows  
Reactor
Dispatcher(分 發器),Notifer(通知器), 事件到來時,使用Dispatcher(分發器)對Handler進行分派,這個Dispatcher要對所有註冊的Handler進行維護。同時,有一 個Demultiplexer(分揀器)對多路的同步事件進行分揀。    

Proactor
Proactor和Reactor都是併發程式設計中的設計模式.用於派發/分離IO操作事件的。這裡所謂的IO事件也就是諸如read/write的IO操作。"派發/分離"就是將單獨的IO事件通知到上層模組。兩個模式不同的地方在於,Proactor用於非同步IO,而Reactor用於同步IO。

兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模組,這個IO操作可以進行或已經完成)。在結構上,兩者也有相同點:demultiplexor負責提交IO操作(非同步)、查詢裝置是否可操作(同步),然後當條件滿足時,就回調handler。
不同點在於,非同步情況下(Proactor),當回撥handler時,表示IO操作已經完成;同步情況下(Reactor),回撥handler時,表示IO裝置可以進行某個操作(can read or can write),handler這個時候開始提交操作。

6.
網路通訊框架