此文已由作者堯飄海授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)。 隨著Node.js的不斷發(fā)展與壯大,應(yīng)用范圍也越來越廣泛,從傳統(tǒng)的企業(yè)應(yīng)用,到互聯(lián)網(wǎng)使用,再到云計(jì)算的發(fā)展,它的身影也是隨處可見。當(dāng)然,它的受歡迎程度能在短時(shí)間內(nèi)得到這么快的發(fā)展,除卻與其本身的事件模型及V8的性能優(yōu)化等一系列特性有關(guān)之外,還和國內(nèi)外很多互聯(lián)網(wǎng)公司的攻城師的大量應(yīng)用和參與到開源項(xiàng)目中有密切關(guān)系,如網(wǎng)易的游戲開發(fā),淘寶的數(shù)據(jù)之美等等。隨著HTML5應(yīng)用和移動互聯(lián)網(wǎng)平臺的指數(shù)增長,越來越多的用戶使用了移動平臺的休閑服務(wù),采用 Node.js 實(shí)現(xiàn)高性能和可擴(kuò)展性的游戲服務(wù)將是一件有意義的工作。 在互聯(lián)網(wǎng)上,目前有一些采用 Node.js 實(shí)現(xiàn)的開源游戲服務(wù)框架,如 Mozilla的 Browser Quest , Google的 Grits ,Chilly等。但是無一例外,這些框架不但與游戲邏輯聯(lián)系緊密,而且?guī)缀鯖]有可擴(kuò)展性和性能數(shù)據(jù),同時(shí)也不提供任何游戲開發(fā)的管理工具,除了采用 JavaScript 編寫外,很難體現(xiàn)出采用 Node.js 實(shí)現(xiàn)游戲開發(fā)的優(yōu)越性。 概念通常游戲分為角色扮演類和策略類及混合類等幾種游戲類型。那么在網(wǎng)頁游戲類型中,根據(jù)游戲的類型,開發(fā)者可能采用不同的架構(gòu)實(shí)現(xiàn)方式,如策略類游戲可能更偏重于游戲的策略性和邏輯性,也就是考驗(yàn)游戲玩家的各種組合或搭配之類的游戲,對實(shí)時(shí)性的要求不會很高,在用戶的可接受范圍之內(nèi)即可,因此也可以采用常用的Web應(yīng)用開發(fā)模式來實(shí)現(xiàn),而客戶端采用輪詢或長連接等方式來實(shí)現(xiàn),這些應(yīng)用模式也有很多的相關(guān)經(jīng)驗(yàn)可以參考,因此能做到具有較好的可擴(kuò)展性及伸縮性;此外,應(yīng)用服務(wù)器和服務(wù)框架等也可以采用現(xiàn)存的技術(shù)實(shí)現(xiàn),但是這只能滿足對游戲?qū)崟r(shí)性要求不高的場景服務(wù),由于此類的應(yīng)用方案非常成熟,在下文的討論中,將不再詳述。 角色扮演類游戲根據(jù)策劃的要求可以實(shí)現(xiàn)各種各樣的功能,如聊天,打斗,自動刷怪等各種復(fù)雜的功能,但是開發(fā)者基本可以把這些功能抽象地劃分為二大類,即服務(wù)端的網(wǎng)絡(luò)傳輸與邏輯運(yùn)算能力,這樣游戲服務(wù)的開發(fā)和實(shí)現(xiàn)會稍微簡單些?,F(xiàn)在,網(wǎng)絡(luò)的實(shí)時(shí)傳輸基本上是采用Socket服務(wù)器來實(shí)現(xiàn)的,邏輯運(yùn)算這個(gè)就不需要再述了,因此,游戲服務(wù)器就可以粗略的歸納為Socket的服務(wù)器綜合游戲業(yè)務(wù)邏輯的實(shí)現(xiàn)。 與Web應(yīng)用區(qū)別從上面游戲服務(wù)的概念簡單介紹中可以得知,實(shí)時(shí)游戲服務(wù)器的開發(fā)與傳統(tǒng)的Web開發(fā)還是具有一些不同點(diǎn),這些不同點(diǎn)著重體現(xiàn)在以下幾個(gè)方面: Web應(yīng)用的場景一般是讀多寫少的應(yīng)用,熱點(diǎn)數(shù)據(jù)基本可以緩存;游戲服務(wù)的數(shù)據(jù)經(jīng)常發(fā)生變動,如移動中的路徑,打怪掉血等,緩存基本很快就失效,屬于寫多讀少的應(yīng)用場景。 廣播特性,即Web應(yīng)用行為上基本只需要用戶與服務(wù)器交互,其他用戶要實(shí)現(xiàn)共享他人信息的時(shí)候,會采用類似拉的方式如長輪詢來實(shí)現(xiàn)數(shù)據(jù)交互,即使在沒有數(shù)據(jù)更新的狀態(tài)時(shí)也需要消耗一定的服務(wù)端資源,造成一定的浪費(fèi);游戲里面的交互方式需要實(shí)時(shí)進(jìn)行,對影響三方的數(shù)據(jù),必須采用廣播的方法進(jìn)行消息推送,即推的模式。 目前的Web應(yīng)用開發(fā)一般采用無狀態(tài)性的方式來實(shí)現(xiàn),因此可以實(shí)現(xiàn)較好的可擴(kuò)展性,很多Web服務(wù)會采用綁定會話或集中會話等方式工作,當(dāng)后面的某臺服務(wù)器出現(xiàn)宕機(jī)時(shí),服務(wù)也可以很快的切換;但是游戲服務(wù)器和用戶之間的連接是有狀態(tài)的,在斷開時(shí)需要進(jìn)行相關(guān)的通知和數(shù)據(jù)持久化,在重連時(shí)需要進(jìn)行狀態(tài)恢復(fù)等手段來維護(hù)游戲世界的運(yùn)行。 除以上幾點(diǎn)不同之外,還有負(fù)載均衡的策略,服務(wù)驅(qū)動方式,系統(tǒng)判定,系統(tǒng)安全如外掛作弊等相關(guān)問題,文章中不再對他們進(jìn)行對比說明。一般來講,根據(jù)游戲的規(guī)模與需求,通常游戲服務(wù)器的實(shí)現(xiàn)的模式會使用如下的三種架構(gòu)方式來實(shí)現(xiàn)。 單進(jìn)程服務(wù)架構(gòu) 圖1 單進(jìn)程服務(wù)架構(gòu) 圖1是目前互聯(lián)網(wǎng)上的很多游戲服務(wù)器使用的架構(gòu),比如商用的SmartFoxServer游戲服務(wù)器,開源的有Google的 Grits, Mozilla的 Browser Quest等框架。所有的程序在同一個(gè)進(jìn)程里面運(yùn)行,架構(gòu)簡單,開發(fā)人員上手快,開發(fā)和調(diào)試非常方便又快速,成本較低,后期的維護(hù)成本可能隨著游戲項(xiàng)目的大小而不同,但是整體應(yīng)該不會太高。很明顯,游戲的世界是在同一個(gè)進(jìn)程里運(yùn)行,在單個(gè)場景都有不少在線用戶的時(shí)候,如果采用單進(jìn)程的 Node.js 實(shí)現(xiàn)的話,每個(gè)用戶的操作可能會有一定的延遲,特別是在大量用戶同時(shí)做大量操作與AI運(yùn)算時(shí),如服務(wù)端尋路和自動殺怪,延遲會更加嚴(yán)重;同時(shí)單進(jìn)程對計(jì)算機(jī)資源使用有限。因此只適合游戲的原型制作或小型的游戲開發(fā)。另外,由于游戲的狀態(tài)與復(fù)雜性,也無法較好的實(shí)現(xiàn)游戲的可擴(kuò)展性,基本只能通過添加游戲服務(wù)器的方式來實(shí)現(xiàn),即所謂的開新服,而這些用戶之間是無法在同一個(gè)世界里通信會話和交互的。盡管Node.js支持原生的TCP服務(wù),使用簡單;但是目前大部分網(wǎng)絡(luò)應(yīng)用中,尤其是支持HTML5的應(yīng)用,由于性能較好并且使用簡單,成為大部分應(yīng)用采用的網(wǎng)絡(luò)庫來實(shí)現(xiàn)高性能websocket服務(wù)。在移動互聯(lián)網(wǎng)應(yīng)用中,由于協(xié)議較復(fù)雜與通信數(shù)據(jù)等問題,需要一定的裁減。下面示例中,就是最簡單的單進(jìn)程服務(wù)的原型:
多進(jìn)程服務(wù)架構(gòu) 圖2 多進(jìn)程服務(wù)架構(gòu) 在上圖2中,我們可以看出,每個(gè)進(jìn)程負(fù)責(zé)采用單一職責(zé),各進(jìn)程間通過一定的規(guī)則(如RPC遠(yuǎn)程過程調(diào)用)來進(jìn)行通信,游戲中的各場景服務(wù)使用一個(gè)進(jìn)程來服務(wù),實(shí)現(xiàn)各場景游戲運(yùn)行的分離。但是在開發(fā)過程中,不需要考慮每個(gè)場景具體的信息,全部采用統(tǒng)一的代碼來實(shí)現(xiàn),開發(fā)方便,通過添加適當(dāng)?shù)膮?shù)來實(shí)現(xiàn)較易的調(diào)試,每個(gè)進(jìn)程分別運(yùn)行在服務(wù)器的多核上,即可以充分使用計(jì)算機(jī)的資源,也由于職責(zé)單一,由于每個(gè)進(jìn)程都專職做自己的事,因此,在壓力大的時(shí)候,可以很明顯的查出問題所在,并可以較好的實(shí)現(xiàn)對相應(yīng)的服務(wù)進(jìn)行調(diào)優(yōu),可以達(dá)到較好的性能和一定的可伸縮性。但是,在各游戲的世界里,無法準(zhǔn)確的知道游戲的狀態(tài)如在線人數(shù)之類的,會存在熱點(diǎn)數(shù)據(jù)和服務(wù)過載等一些問題,造成部分服務(wù)堵死等現(xiàn)象,也無法達(dá)到在不停服務(wù)的情況下進(jìn)行服務(wù)器擴(kuò)容與自動切換等問題,同時(shí)會給游戲運(yùn)營帶來一定的問題,不能充分的對玩家數(shù)據(jù)進(jìn)行分析與挖掘,因此,這種實(shí)現(xiàn)方式可以滿足中小型的游戲開發(fā)。這種架構(gòu)目前很多的游戲服務(wù)器中還在使用,技術(shù)發(fā)展也較成熟,如傳奇服務(wù)端架構(gòu)等。 分布式服務(wù)架構(gòu) 圖3 分布式的服務(wù)架構(gòu) 同樣,分布式的服務(wù)架構(gòu)與多進(jìn)程的架構(gòu)具有很多相同點(diǎn),如進(jìn)程服務(wù)單一職責(zé),較好的性能調(diào)優(yōu),同時(shí)采用集中式的方式對游戲服務(wù)器進(jìn)行管理,各游戲服務(wù)器可以通過自定義的方式即DSL進(jìn)行游戲業(yè)務(wù)的路由與分發(fā),通過主備服務(wù)器的狀態(tài)可以很清楚的知道每個(gè)服務(wù)的狀態(tài)及運(yùn)行情況,這樣可通過動態(tài)添加服務(wù)來到達(dá)負(fù)載均衡,具備較好的性能和可擴(kuò)展性,能滿足大型游戲的開發(fā)。當(dāng)然,采用這樣方式,會具有一定的復(fù)雜性,同時(shí)各服務(wù)之間可能是不在同一臺服務(wù)器上的,因此會帶來一定的網(wǎng)絡(luò)開銷,在大量廣播的場景中,網(wǎng)絡(luò)IO壓力大,需要通過定時(shí)批量或AOI服務(wù)等方式來進(jìn)行廣播通信,同時(shí),游戲的通信協(xié)議需要經(jīng)過特別的設(shè)計(jì),盡量避免數(shù)據(jù)序列化上的CPU重復(fù)開銷,采用胖客戶端的方式去分擔(dān)游戲服務(wù)器的序列化與反序列化;另外還有可能引入分布式事務(wù)等相關(guān)問題,需要在一個(gè)集中點(diǎn)進(jìn)行處理。當(dāng)然,在游戲設(shè)計(jì)中,策劃開發(fā)人員需要盡量避免這種跨場景跨進(jìn)程的游戲邏輯需求。 在分布式架構(gòu)實(shí)現(xiàn)中,目前商業(yè)上較成功的案例是BigWorld游戲服務(wù)框架,國內(nèi)外很多大型的游戲開發(fā)商都在使用。而在開源部分,目前還沒有較穩(wěn)定成熟的方案,我們團(tuán)隊(duì)采用Node.js正在開發(fā)的Pomelo游戲服務(wù)框架正在努力實(shí)現(xiàn)這一目標(biāo),現(xiàn)已進(jìn)入最后的文檔整理階段,預(yù)計(jì)將在十月份進(jìn)行開源與線上示例演示。 總結(jié)<span style="display: inline !important; float: none; background-color: transparent; color: rgb(51, 相關(guān)文章: Node.js之網(wǎng)游服務(wù)器實(shí)踐的更多相關(guān)文章
隨機(jī)推薦
|
|