版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、游戲服務(wù)端所完成的事情(一)從定義問題開始,簡單直接地說,一套游戲服務(wù)端開發(fā)框架應(yīng)該具有下面兩種能力:· 定義了client到server、server到client、server到server的消息pipeline。· 描述了游戲世界狀態(tài)的維護方式。1 消息pipeline1.1 經(jīng)典消息pipeline1.1.1 場景同步當(dāng)討論到游戲服務(wù)端的時候,我們首先想到的會是什么?要回答這個問題,我們需要從游戲服務(wù)端的需求起源說起。定義問題游戲?qū)Ψ?wù)端的需求起源應(yīng)該有兩個:· 第一種是單機游戲聯(lián)網(wǎng)版,實現(xiàn)為主客機模式的話,主機部分可以看做服務(wù)端。· 第二種是所
2、有mmo的雛形mud,跟webserver比較類似,一個host服務(wù)多clients,表現(xiàn)為cs架構(gòu)。第一種需求長盛不衰,一方面是console游戲特別適合這一套,另一方面是最近幾年手游起來了,碎片化的PVE玩法+開房間式同步PVP玩法也得到驗證,畢竟MMO手游再怎么火也不可能改變手游時間碎片化的事實的,最近的皇家沖突也證明,手游不會再重走端游老路了。第二種需求就不用說了,網(wǎng)上大把例子可以參考。最典型的是假設(shè)有這樣一塊野地,上面很多玩家和怪,邏輯都在服務(wù)端驅(qū)動,好了,這類需求沒其他額外的描述了。但是,解決方案畢竟是不斷發(fā)展的,即使速度很慢。說不斷發(fā)展是特指針對第一種需求的解決方案,發(fā)展原因就是
3、國情,外掛太多。像war3這種都還是純正的主客機,但是后來對戰(zhàn)平臺出現(xiàn)、發(fā)展,逐漸過渡成了cs架構(gòu)。真正的主機 其實是建在服務(wù)器的,這樣其實服務(wù)器這邊也維護了房間狀態(tài)。后來的一系列ARPG端游也都是這個趨勢,服務(wù)端越來越重,逐漸變得與第二種模式?jīng)]什么區(qū)別。 同理如現(xiàn)在的各種ARPG手游。說發(fā)展速度很慢特指針對第二種需求的解決方案,慢的原因也比較有意思,那就是wow成了不可逾越的鴻溝。bigworld在wow用之前名不見經(jīng)傳,wow用了之后國內(nèi)廠商也跟進。發(fā)展了這么多年,現(xiàn)在的無縫世界服務(wù)端跟當(dāng)年的無縫世界服務(wù)端并無二致。發(fā)展慢的原因就觀察來說可能需求本身就不是特別明確,MMO核心用戶是重社交的
4、,無縫世界核心用戶是重體驗的。前者跑去玩了天龍八部和倩女不干了,說這倆既輕松又妹子多;后者玩了console游戲也不干了,搞了半天MMO無縫世界是讓我更好地刷刷刷的。所以仔細想想,這么多年了,能數(shù)得上的無縫世界游戲除了天下就是劍網(wǎng),收入跟重社交的那幾款完全不在一個量級。兩種需求起源,最終其實導(dǎo)向了同一種業(yè)務(wù)需求。傳統(tǒng)MMO架構(gòu)(就是之前說的天龍、倩女類架構(gòu)),一個進程維護多個場景,每個場景里多個玩家,額外的中心進程負責(zé)幫玩家從一個場景/進程切到另一個場景/進程。bigworld架構(gòu),如果剝離開其圍繞切進程所做的一些外圍設(shè)施,核心工作流程基本就能用這一段話描述。抽象一下問題,那我們談到游戲服務(wù)端
5、首先想到的就應(yīng)該是多玩家對同一場景的view同步,也就是場景服務(wù)。本節(jié)不會討論幀同步或是狀態(tài)同步這種比較上層的問題,我們將重點放在數(shù)據(jù)流上。如何實現(xiàn)場景同步?首先,我們看手邊工具,socket。之所以不提TCP或UDP是因為要不要用UDP自己實現(xiàn)一套TCP是另一個待撕話題,這篇文章不做討論。因此,我們假設(shè),后續(xù)的實現(xiàn)是建立在對底層協(xié)議一無所知的前提之上的,這樣設(shè)計的時候只要適配各種協(xié)議,到時候就能按需切換。socket大家都很熟悉,優(yōu)點就是各操作系統(tǒng)上抽象統(tǒng)一。因此,之前的問題可以規(guī)約為:如何用socket實現(xiàn)場景同步?拓撲結(jié)構(gòu)是這樣的(之后的所有圖片連接箭頭的意思表示箭頭指向的對于箭頭起源的
6、來說是靜態(tài)的):場景同步有兩個需求:· low latency· rich interaction要做到前者,最理想的情況就是由游戲程序員把控消息流的整套pipeline,換句話說,就是不借助第三方的消息庫/連接庫。當(dāng)然,例外是你對某些第三方連接庫特別熟悉,比如很多C+服務(wù)端庫喜歡用的libevent,或者我在本篇文章提供的示例代碼所依賴的,mono中的IO模塊。要做到后者,就需要保持場景同步邏輯的簡化,也就是說,場景邏輯最好是單線程的,并且跟IO無關(guān)。其核心入口就是一個主循環(huán),依次更新場景中的所有entity,刷新狀態(tài),并通知client。正是由于這兩個需求的存在,網(wǎng)絡(luò)庫
7、的概念就出現(xiàn)了。網(wǎng)絡(luò)庫由于易于實現(xiàn),概念簡單,而且籠罩著“底層”光環(huán),所以如果除去玩具性質(zhì)的項目之外,網(wǎng)絡(luò)庫應(yīng)該是程序員造過最多的輪子之一。那么,網(wǎng)絡(luò)庫解決了什么問題?拋開多項目代碼復(fù)用不談,網(wǎng)絡(luò)庫首先解決的一點就是,將傳輸層的協(xié)議(stream-based的TCP協(xié)議或packet-based的UDP協(xié)議)轉(zhuǎn)換為應(yīng)用層的消息協(xié)議(通常是packet-based)。對于業(yè)務(wù)層來說,接收到流和包的處理模型是完全不同的。對于業(yè)務(wù)邏輯狗來說,包顯然是處理起來更直觀的。流轉(zhuǎn)包的方法很多,最簡單的可伸縮的non-trivial buffer,ringbuffer,bufferlist,不同的結(jié)構(gòu)適用于不
8、同的需求,有的方便做zero-copy,有的方便做無鎖,有的純粹圖個省事。因為如果沒有個具體的testcast或者benchmark,誰比誰一定好都說不準(zhǔn)。buffer需要提供的語義也很簡單,無非就是add、remove。buffer是只服務(wù)于網(wǎng)絡(luò)庫的。網(wǎng)絡(luò)庫要解決的第二個問題是,為應(yīng)用層建立IO模型。由于之前提到過的場景服務(wù)的rich interaction的特點,poll模型可以避免大量共享狀態(tài)的存在,理論上應(yīng)該是最合適場景服務(wù)的。所謂poll,就是IO線程準(zhǔn)備好數(shù)據(jù)放在消息隊列中,用戶線程負責(zé)輪詢poll,這樣,應(yīng)用層的回調(diào)就是由用戶線程進入的,保證模型簡單。而至于IO線程是如何準(zhǔn)備數(shù)據(jù)
9、的,平臺不同做法不同。linux上最合適的做法是reactor,win最合適的做法就是proactor,一個例外是mono,mono跑在linux平臺上的時候雖然IO庫是reactor模型,但是在C#層面還是表現(xiàn)為proactor模型。提供統(tǒng)一poll語義的網(wǎng)絡(luò)庫可以隱藏這種平臺差異,讓應(yīng)用層看起來就是統(tǒng)一的本線程poll,本線程回調(diào)。網(wǎng)絡(luò)庫要解決的第三個問題是,封裝具體的連接細節(jié)。cs架構(gòu)中一方是client一方是server,因此連接細節(jié)在兩側(cè)是不一樣的。而由于socket是全雙工的,因此之前所說的IO模型對于任意一側(cè)都是適用的。連接細節(jié)的不同就體現(xiàn)在,client側(cè),核心需求是發(fā)起建立連
10、接,外圍需求是重連;server側(cè),核心需求是接受連接,外圍需求是主動斷開連接。而兩邊等到連接建立好,都可以基于這個連接構(gòu)建同樣的IO模型就可以了?,F(xiàn)在,簡單介紹一種網(wǎng)絡(luò)庫實現(xiàn)。· 一個連接好的socket對應(yīng)一個connector。· connector負責(zé)向上提供IO模型抽象(poll語義)。同時,其借助維護的一個connector_buffer,來實現(xiàn)流轉(zhuǎn)包。· 網(wǎng)絡(luò)庫中的client部分主要組件是ClientNetwork,維護連接(與重連)與一條connector。· 網(wǎng)絡(luò)庫中的server部分主要組件是ServerNetwork,維護接受連接
11、(與主動斷開)與N條connector。· Network層面的協(xié)議非常簡單,就是len+data。具體代碼不再在博客里貼了。請參考:Network引入新的問題如果類比馬斯洛需求中的層次,有了網(wǎng)絡(luò)庫,我們只能算是解決了生理需求:可以聯(lián)網(wǎng)。但是后面還有一系列的復(fù)雜問題。最先碰到的問題就是,玩家數(shù)量增加,一個進程扛不住了。那么就需要多個進程,每個進程服務(wù)一定數(shù)量的玩家。但是,給定任意兩個玩家,他們總有可能有交互的需求。對于交互需求,比較直觀的解決方案是,讓兩個玩家在各自的進程中跨進程交互。但是這就成了一個分布式一致性問題兩個進程中兩個玩家的狀態(tài)需要保持一致。至于為什么一開始沒人這樣做,我
12、只能理解為,游戲程序員的計算機科學(xué)素養(yǎng)中位程度應(yīng)該解決不了這么復(fù)雜的問題。因此比較流行的是一種簡單一些的方案。場景交互的話,就限定兩個玩家必須在同一場景(進程),比如攻擊。其他交互的話,就借助第三方的協(xié)調(diào)者來做,比如公會相關(guān)的通常會走一個全局服務(wù)器等等。這樣,服務(wù)端就由之前的單場景進程變?yōu)榱硕鄨鼍斑M程+協(xié)調(diào)進程。新的問題出現(xiàn)了:玩家需要與服務(wù)端保持多少條連接?一種方法是保持O(n)條連接,既不環(huán)保,擴展性又差,可以直接pass掉。那么就只能保持O(1)條連接,如此的話,如何確定玩家正與哪個服務(wù)端進程通信?要解決這個問題,我們只能引入新的抽象。 1.1.2 Gate定義問題整理下我們的
13、需求:· 玩家在服務(wù)端的entity可以在不同的進程中,也可以移動到同一個進程中。· 玩家只需要與服務(wù)端建立有限條連接,即有訪問到任意服務(wù)端進程的可能性。同時,這個連接數(shù)量不會隨服務(wù)端進程數(shù)量增長而線性增長。要解決這些需求,我們需要引入一種反向代理(reverse proxy)中間件。反向代理是服務(wù)端開發(fā)中的一種常見基礎(chǔ)設(shè)施抽象(infrastructure abstraction),概念很簡單,簡單說就是內(nèi)網(wǎng)進程不是借助這種proxy訪問外部,而是被動地掛在proxy上,等外部通過這種proxy訪問內(nèi)部。更具體地說,反向代理就是這樣一種server:它接受clients連
14、接,并且會將client的上行包轉(zhuǎn)發(fā)給后端具體的服務(wù)端進程。很多年前l(fā)inux剛支持epoll的時候,流行一個c10k的概念,解決c10k問題的核心就是借助性能不錯的反向代理中間件。游戲開發(fā)中,這種組件的名字也比較通用,通常叫Gate。Gate解決了什么問題· 首先,Gate作為server,可以接受clients的連接。這里就可以直接用我們上一節(jié)輸出的網(wǎng)絡(luò)庫。同時,其可以接受服務(wù)端進程(之后簡稱backend)的連接,保持通信。· 其次,Gate能夠?qū)lients的消息轉(zhuǎn)發(fā)到對應(yīng)的backend。與此對應(yīng)的,backend可以向Gate訂閱自己關(guān)注的client消息。對
15、于場景服務(wù)來說,這里可以增加一個約束條件,那就是限制client的上行消息不會被dup,只會導(dǎo)到一個backend上。僅就這兩點而言,Gate已經(jīng)能夠解決上一節(jié)末提出的需求。做法就是client給消息加head,其中的標(biāo)記可以供Gate識別,然后將消息路由到對應(yīng)的backend上。比如公會相關(guān)的消息,Gate會路由到全局進程;場景相關(guān)的消息,Gate會路由到訂閱該client的場景進程。同時,玩家要切場景的時候,可以由特定的backend(比如同樣由全局進程負責(zé))調(diào)度,讓不同的場景進程向Gate申請修改對client場景相關(guān)消息的訂閱關(guān)系,以實現(xiàn)將玩家的entity從場景進程A切到場景進程B。
16、站在比需求更高的層次來看Gate的意義的話,我們發(fā)現(xiàn),現(xiàn)在clients不需要關(guān)注backends的細節(jié),backends也不需要關(guān)注clients的細節(jié),Gate成為這一pipeline中唯一的靜態(tài)部分(static part)當(dāng)然,Gate能解決的還不止這些。我們考慮場景進程最常見的一種需求。玩家的移動在多client同步。具體的流程就是,client上來一個請求移動包,路由到場景進程后進行一些檢查、處理,再推送一份數(shù)據(jù)給該玩家及附近所有玩家對應(yīng)的clients。如果按之前說的,這個backend就得推送N份一樣的數(shù)據(jù)到Gate,Gate再分別轉(zhuǎn)給對應(yīng)的clients。這時,就出現(xiàn)了對組播
17、(multicast)的需求。組播是一種通用的message pattern,同樣也是發(fā)布訂閱模型的一種實現(xiàn)方式。就目前的需求來說,我們只需要為client維護組的概念,而不需要做inter-backend組播。這樣,backend需要給多clients推送同樣的數(shù)據(jù)時,只需要推送一份給Gate,Gate再自己dup就可以了盡管帶來的好處有限,但是還是能夠一定程度降低內(nèi)網(wǎng)流量。那接下來就介紹一種Gate的實現(xiàn)。我們目前所得出的Gate模型其實包括兩個組件:· 針對路由client消息的需求,這個組件叫Broker。Broker的定義可以參考zguide對DEALER+ROUTER p
18、attern的介紹。Broker的工作就是將client的消息導(dǎo)向?qū)?yīng)的backend。· 針對組播backend消息的需求,這個組件叫Multicast。簡單來說就是維護一個組id到clientIdList的映射。Gate的工作流程就是,listen兩個端口,一個接受外網(wǎng)clients連接,一個接受內(nèi)網(wǎng)backends連接。Gate有自己的協(xié)議,該協(xié)議基于Network的len+data協(xié)議之上構(gòu)建。clients的協(xié)議處理組件與backends的協(xié)議處理組件不同,前者只處理部分協(xié)議(不會識別組控制相關(guān)協(xié)議,訂閱協(xié)議)。在具體的實現(xiàn)細節(jié)上,判斷一個client消息應(yīng)該路由到哪個ba
19、ckend,需要至少兩個信息:一個是clientId,一個是key。同一個clientId的消息有可能會路由到不同的backend上。當(dāng)然,Gate的協(xié)議設(shè)計可以自由發(fā)揮,將clientId+key組成一個routingKey也是可以的。引入Gate之后的拓撲: 具體代碼請參考:GateSharp引入新的問題現(xiàn)在我們在需求的金字塔上更上了一層。之前我們是擔(dān)心玩家數(shù)量增長會導(dǎo)致服務(wù)端進程爆掉,現(xiàn)在我們已經(jīng)可以隨意擴容backend進程,我們還可以通過額外實現(xiàn)的全局協(xié)調(diào)者進程來實現(xiàn)Gate的多開與動態(tài)擴容。甚至,我們可以通過構(gòu)建額外的中間層,來實現(xiàn)服務(wù)端進程負載動態(tài)伸縮,比如像bigwo
20、rld那樣,在場景進程與Gate之間再隔離出一層玩家agent層??梢哉f,在這種方案成熟之后,程序員之間開始流行“游戲開發(fā)技術(shù)封閉”這種說法了。為什么?舉一個簡單的例子,大概描述下現(xiàn)在一個游戲項目的服務(wù)端生命周期狀況:· 第一階段,大概到目前這篇文章的進度為止,實現(xiàn)了場景內(nèi)跑跳打。· 第二階段,瘋狂地為場景進程增加邏輯,各種跟游戲有關(guān)的邏輯全加進來,直到這部分的代碼量占到整個服務(wù)端代碼量的80%以上。· 第三階段,有節(jié)操的程序員考慮拆分進程,當(dāng)然,一開始的協(xié)調(diào)者進程一直都會存在,畢竟有些需求是場景進程無論如何都實現(xiàn)不了的。拆分進程的典型例子有聊天、郵件、公會等等。
21、拆分出來的進程基本上是對場景進程代碼輪廓的拷貝粘貼,刪掉邏輯就開始在這之上寫了。結(jié)果就是,產(chǎn)出了幾個玩具水平的服務(wù)器進程。要非得說是工業(yè)級或者生產(chǎn)環(huán)境級別的吧,也算是,畢竟bugfix的代碼的體量是玩具項目比不了的。而且,為了更好地bugfix,通常會引入lua或者python,然后游戲邏輯全盤由腳本構(gòu)建,這下更方便bugfix了,還是hotfix的,那開發(fā)期就更能隨便寫寫寫了,你說架構(gòu)是什么東西? 至于具體拓撲,可以對著下圖腦補一下,增加N個節(jié)點,N個節(jié)點之間互相連接。玩具水平的項目再修修補補,也永遠不會變成工藝品。skynet別的不說,至少實現(xiàn)了一套輕量級的actor model,做服務(wù)分離更自然,服務(wù)間的拓撲一目了然,連接拓撲更是優(yōu)雅。網(wǎng)易的mobile_serve
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 【同步輔導(dǎo)】2021高中數(shù)學(xué)北師大版必修四導(dǎo)學(xué)案:《任意角的正弦函數(shù)、余弦函數(shù)的定義與周期性》
- 征收土地補償標(biāo)準(zhǔn)2022年
- 甘肅省平?jīng)鍪星f浪縣2024-2025學(xué)年高一上學(xué)期第二學(xué)段考數(shù)學(xué)試題(含答案)
- 【備課參考】2020年新人教版高中地理必修1:課堂實錄2.2《氣壓帶和風(fēng)帶》
- 安徽省滁州市來安縣部分學(xué)校2024-2025學(xué)年第一學(xué)期八年級語文期末試卷(含答案)
- 2024-2025學(xué)年湖南省岳陽市高中教學(xué)質(zhì)量監(jiān)測試卷高一數(shù)學(xué)試題(含解析)
- 《淺談當(dāng)下護士意識》課件
- 《金版教程》2022屆高考生物一輪總復(fù)習(xí)階段示范性金考卷1-
- 【名師一號】2020-2021學(xué)年高中地理中圖版必修三-雙基限時練(九)
- 2022屆高考語文第一輪復(fù)習(xí)-第3部分論述類文本閱讀常見題型(復(fù)習(xí)課)
- 二年級上冊數(shù)學(xué)豎式計算300道帶答案
- 國開《當(dāng)代中國政治制度》機考復(fù)習(xí)題匯總
- (2024年)數(shù)據(jù)分析PPT圖片
- 燃氣熱水鍋爐操作規(guī)程培訓(xùn)
- 中醫(yī)院醫(yī)院設(shè)備科工作總結(jié)
- JC/T 414-2017 硅藻土行業(yè)標(biāo)準(zhǔn)
- 組織學(xué)與胚胎學(xué)課程教學(xué)大綱
- 網(wǎng)絡(luò)傳播概論(第5版) 課件 第一章 網(wǎng)絡(luò)媒介的演變
- 玻璃硝酸鉀加硬工藝
- 2023-2024學(xué)年江西省鷹潭市余江區(qū)八年級(上)期末數(shù)學(xué)試卷(含解析)
- 2023北京西城六年級(上)期末英語試卷含答案
評論
0/150
提交評論