文/Matchvs

導(dǎo)語:本文嘗試從開發(fā)者角度梳理開發(fā)實(shí)時聯(lián)網(wǎng)游戲后臺服務(wù)過程中可能面臨的挑戰(zhàn),并針對性地提供相應(yīng)解決思路,期望幫助開發(fā)者依據(jù)自身游戲特點(diǎn)做出合理的技術(shù)選型。

維基百科關(guān)于網(wǎng)絡(luò)游戲的定義:通過計(jì)算機(jī)網(wǎng)絡(luò),將專用服務(wù)器和用戶的客戶端設(shè)備(手機(jī)、PC、游戲主機(jī)等)相連,讓多名玩家同時聯(lián)機(jī)進(jìn)行游戲的娛樂形式,由此可知網(wǎng)絡(luò)游戲涉及三個角色:客戶端、網(wǎng)絡(luò)、服務(wù)器,從網(wǎng)絡(luò)架構(gòu)上來講網(wǎng)絡(luò)游戲可分為C/S 架構(gòu)和P2P架構(gòu)(特指客戶端間直連通信),在實(shí)際開發(fā)中還有一種C/S和P2P架構(gòu)混合:C/M架構(gòu)。

135426gi9dtnysdss4ys9h.png
其中4層以下都由操作系統(tǒng)來負(fù)責(zé),開發(fā)者無需為此操心,在實(shí)際的開發(fā)過程中開發(fā)者首要面臨的問題便是傳輸層是采用TCP還是UDP,下表簡要對比了兩者的優(yōu)劣。 綜合兩者優(yōu)劣,簡單來說除非對延遲有極致要求(例如FPS、MOBA類游戲)需采用UDP外,TCP可應(yīng)對大部分游戲。

在實(shí)際游戲開發(fā)中不管是采用TCP還是UDP方式,都較少利用通過Socket編程方式直接進(jìn)行,一來因?yàn)殚_發(fā)工作量大,質(zhì)量性能難以保證;二來平臺兼容性不好(比如H5并沒有提供socket編程能力),而是基于更上層的通訊協(xié)議比如基于TCP的HTTP、Websocket協(xié)議,GRPC,以及基于UDP實(shí)現(xiàn)的QUIC,WebRTC協(xié)議等。

135427mdipslplmalk67t6.jpg
值得注意的是基于安全性考慮,瀏覽器標(biāo)準(zhǔn)未提供UDP收發(fā)能力,QUIC協(xié)議也只在chrome得到了支持,WebRTC也還不是瀏覽器事實(shí)標(biāo)準(zhǔn)且協(xié)議初始目的是用于實(shí)現(xiàn)點(diǎn)對點(diǎn)的音視頻通信,協(xié)議內(nèi)容過于龐雜不容易提煉應(yīng)用于游戲開發(fā)中,因而現(xiàn)階段H5游戲還只能采用HTTP或Websocket方式通訊。

通訊協(xié)議確定后,隨后要考慮的便是游戲?qū)ο蟮男蛄谢?,序列化主要有基于文本、基于二進(jìn)制兩種,其優(yōu)劣如下表所示。在開發(fā)過程中一般會先采用文本序列化方式,便于前后端開發(fā)聯(lián)調(diào),在游戲正式上線前切換至二進(jìn)制序列化方式以減少傳輸流量、提升編解碼效率。

135427gzktgad1widus89c.jpg
至于數(shù)據(jù)安全性問題,為了保護(hù)敏感數(shù)據(jù)安全開發(fā)者可以選擇安全的https或WSS通訊協(xié)議,而對于直接基于TCP協(xié)議通訊,可采用先用RSA協(xié)商加密秘鑰,然后使用對稱加密方式將數(shù)據(jù)加密后發(fā)送。

通過以上分析,對于游戲協(xié)議類型的選擇我們給出有以下準(zhǔn)則:

1、弱聯(lián)網(wǎng)類游戲:諸如休閑、卡牌類游戲可直接HTTP協(xié)議,對安全性有要求的話就使用HTTPS;

2、實(shí)時性,交互性要求較高:這類游戲一般需要保持長連接,優(yōu)先選擇標(biāo)準(zhǔn)的ws協(xié)議(同時使用二進(jìn)制序列化方式),如考慮安全性可使用wss協(xié)議。而對于提供socket接口的native平臺也可使用TCP協(xié)議,同時對數(shù)據(jù)做對稱加密增強(qiáng)安全性;

3、實(shí)時性要求極高:不僅需要和服務(wù)器保持長連接,且延遲和網(wǎng)絡(luò)抖動都要求極高(如FPS,賽車類游戲),可使用基于UDP的實(shí)現(xiàn)流傳輸協(xié)議如QUIC,KCP等。

02、并發(fā)模型

為了處理來自客戶端的并發(fā)請求,服務(wù)端有4種常見的并發(fā)模型。

2.1進(jìn)程

進(jìn)程是最早采用的并發(fā)模型,進(jìn)程作為操作資源分配、調(diào)度的單位,擁有獨(dú)立的運(yùn)行空間。進(jìn)程并發(fā)模型中每個請求由獨(dú)立的進(jìn)程來處理,進(jìn)程一次只能處理一個請求,該模型最大的優(yōu)點(diǎn)就是簡單。如果處理請求的進(jìn)程由于系統(tǒng)調(diào)用而阻塞或進(jìn)程的時間片用完,搶占式的進(jìn)程調(diào)度器就會暫停舊進(jìn)程執(zhí)行,調(diào)度執(zhí)行新的進(jìn)程,這個過程涉及大開銷的上下文切換,進(jìn)程并發(fā)模型的缺點(diǎn)是比較低效。最典型的采用進(jìn)程模型的服務(wù)有Apache。

2.2線程

線程并發(fā)模型是進(jìn)程模型的改進(jìn),線程從屬于進(jìn)程,是系統(tǒng)更小粒度的執(zhí)行調(diào)度單元。不同請求可由進(jìn)程內(nèi)多個并發(fā)執(zhí)行的線程來處理,這些線程由操作系統(tǒng)內(nèi)核自動調(diào)度。線程相對進(jìn)程的主要優(yōu)勢在于,調(diào)度上下文切換開銷更小,但由于多個線程共享地址空間,需要額外的線程間互斥、同步機(jī)制來保證程序性正確性。典型的采用線程模型的服務(wù)有Tomcat。

2.3 IO多路復(fù)用

利用操作系統(tǒng)提供的epoll等IO多路復(fù)用機(jī)制,能同時監(jiān)控多個連接上讀、寫事件, IO多路復(fù)用也稱事件驅(qū)動模型,網(wǎng)絡(luò)程序執(zhí)行邏輯可抽象為事件驅(qū)動的狀態(tài)機(jī)。 IO多路復(fù)用避免了讀寫阻塞,減少了上下文切換,提升了CPU利用率和系統(tǒng)吞吐率。但I(xiàn)O多路復(fù)用它將原本“同步”、線性的處理邏輯變成事件驅(qū)動的狀態(tài)機(jī),處理邏輯分散于大量的事件回調(diào)函數(shù)。這種異步、非線性的模型,極大地增加了編程難度,如nodeJs的常見的回調(diào)地獄問題。典型的采用IO復(fù)用模型的服務(wù)有Nginx,netty。

2.4 協(xié)程

協(xié)程也稱為輕量級線程,是一種協(xié)同的、非搶占式的多任務(wù)并發(fā)模型。 協(xié)程運(yùn)行在用戶空間,當(dāng)遇到阻塞或特定入口時,通過顯式調(diào)用切換方法主動讓出CPU,由任務(wù)調(diào)度器選取另一個協(xié)程執(zhí)行。

協(xié)程切換只是簡單地改變執(zhí)行函數(shù)棧,不涉及內(nèi)核態(tài)與用戶態(tài)轉(zhuǎn)化,也涉及上下文切換,開銷遠(yuǎn)小于進(jìn)程/線程切換。協(xié)程的概念雖早已提出,隨著近些年年越來越多的語言(go、 Haskell)內(nèi)置對協(xié)程支持才被開發(fā)者所熟知,協(xié)程極大的優(yōu)化了開發(fā)者編程體驗(yàn),在同步、順序編程風(fēng)格能快速實(shí)現(xiàn)程序邏輯,還擁有IO多路復(fù)用異步編程的性能。典型的采用協(xié)程模型的服務(wù)有openresty(Lua), gevent(Python), golang。

以上總結(jié)了目前4種常用的并發(fā)模型,它們在工作原理、運(yùn)行效率、編程難度等方面有顯著區(qū)別,各自有適用場景,在實(shí)際使用時應(yīng)該根據(jù)需求仔細(xì)評估。在實(shí)際開發(fā)過程中如果沒有可復(fù)用的現(xiàn)成網(wǎng)絡(luò)組件或歷史包袱我們建議使用協(xié)程并發(fā)模式開發(fā)網(wǎng)絡(luò)接入層服務(wù)。

via: 游戲扶持by騰訊游戲?qū)W院


銳亞教育

銳亞教育,游戲開發(fā)論壇|游戲制作人|游戲策劃|游戲開發(fā)|獨(dú)立游戲|游戲產(chǎn)業(yè)|游戲研發(fā)|游戲運(yùn)營| unity|unity3d|unity3d官網(wǎng)|unity3d 教程|金融帝國3|8k8k8k|mcafee8.5i|游戲蠻牛|蠻牛 unity|蠻牛