溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎樣只基于請(qǐng)求回應(yīng)模式實(shí)現(xiàn)MMO級(jí)別的場(chǎng)景服務(wù)

發(fā)布時(shí)間:2021-12-21 14:47:08 來源:億速云 閱讀:116 作者:柒染 欄目:大數(shù)據(jù)

這篇文章給大家介紹怎樣只基于請(qǐng)求回應(yīng)模式實(shí)現(xiàn)MMO級(jí)別的場(chǎng)景服務(wù),內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

從本質(zhì)上來說,如果你只是想把一系列消息發(fā)送到客戶端,req/resp 請(qǐng)求回應(yīng)模式和 pub/sub 發(fā)布訂閱模式并沒有什么不同。你可以把 req/resp 理解成一次性的,只訂閱一條(或有限條)消息;如果需要維持這類消息的推送,需要客戶端在收到消息后再次發(fā)起訂閱。

這和 timer 定時(shí)器系統(tǒng)一樣,訂閱一個(gè)定期觸發(fā)的定時(shí)器這種功能并非必要。如果你需要一個(gè)每分鐘觸發(fā)一次的定時(shí)器,完全可以在觸發(fā)一次定時(shí)操作后,立刻發(fā)起下一次定時(shí)任務(wù)請(qǐng)求。它在功能上是等價(jià)的。

潛在的實(shí)時(shí)性影響是:如果規(guī)定必須在收到回應(yīng)消息后,才允許發(fā)起下一次請(qǐng)求;那么一個(gè)事件發(fā)生后推送到客戶端的延遲可能增加了最多 2 倍。即,如果你剛剛回應(yīng)了一條消息,這個(gè)時(shí)候又發(fā)生了新的事件;客戶端需要在收到前一個(gè)事件后再提起新請(qǐng)求,然后你才可以把后發(fā)生的事件通過新請(qǐng)求的回應(yīng)包發(fā)過去。

降低這個(gè)實(shí)時(shí)性影響的方法也很簡(jiǎn)單,協(xié)議上允許在客戶端發(fā)起請(qǐng)求后未收到回應(yīng)之前再次發(fā)起請(qǐng)求即可。對(duì)應(yīng)同類消息許多少并發(fā)的請(qǐng)求,要根據(jù)這類消息的實(shí)時(shí)性要求有多高來決定。無限提高允許的并發(fā)量沒有太大意義,畢竟物理上的延遲不可能完全消除。

從客戶端來看,MMO 這樣的游戲,客戶端僅僅是一個(gè)呈現(xiàn)設(shè)備,它不斷的接收到服務(wù)器發(fā)過來的游戲世界的狀態(tài)變化,而做出表現(xiàn)??蛻舳酥饕炕貞?yīng)包來分發(fā)業(yè)務(wù)邏輯,使用請(qǐng)求回應(yīng)模式,無非是根據(jù)回應(yīng)包里的 session 號(hào)匹配之前請(qǐng)求包(通常包的類型在請(qǐng)求包中,不必放在回應(yīng)包數(shù)據(jù)里),將兩者(請(qǐng)求/回應(yīng))合并起來調(diào)用消息分發(fā)函數(shù)而已。

既然效果一樣,請(qǐng)求回應(yīng)模式有更大的數(shù)據(jù)冗余(一些看起來沒有意義的請(qǐng)求包,在訂閱模式中,你可能只需要訂閱一次)那么請(qǐng)求回應(yīng)模式帶來的好處是什么呢?

  1. 它天然可以解決過載問題。如果服務(wù)器不考慮客戶端的帶寬/硬件處理能力而推送數(shù)據(jù),客戶端很可能無法及時(shí)處理,而無謂的浪費(fèi)了雙方的帶寬。而請(qǐng)求/回應(yīng)模式中,如果我還沒處理完,就不會(huì)要更多,很自然的回避了問題。

  2. 有選擇性的發(fā)送消息這件事,對(duì)服務(wù)器來說,要么是一個(gè)時(shí)間復(fù)雜度為 O(n2) 的操作:你需要對(duì)每個(gè)用戶遍歷對(duì)比其他用戶來決定這條消息對(duì)方是否關(guān)心;要么,會(huì)把數(shù)據(jù)結(jié)構(gòu)的復(fù)雜度提高一個(gè)數(shù)量級(jí):你需要把對(duì)象進(jìn)行各種分類、索引,以提高檢索的效率。而如果把選擇我關(guān)心的消息的權(quán)利放在客戶端,那么時(shí)間復(fù)雜度就只有 O(n) 了??蛻舳丝偰芨私庾约旱那闆r。我是 iphone6s ,所以我可以關(guān)心我周圍 50 個(gè)人的變化;你用個(gè)兩年前的紅米,屏蔽了周圍所有人,服務(wù)器就不要把我旁邊的人跳了個(gè)舞的事件發(fā)給我了。

  3. 消息優(yōu)先級(jí)更好處理。我正在戰(zhàn)斗,那些在世界聊天頻道對(duì)撕的消息晚點(diǎn)給我,不要耽誤了我的對(duì)手正在搓火球這種我更關(guān)心的事件。

  4. 無論是客戶端還是服務(wù)器,只要想清楚,業(yè)務(wù)邏輯可以寫得更清晰。怎么做呢,下面展開講。


在 MMO 的場(chǎng)景服務(wù)中,只使用請(qǐng)求回應(yīng)模式該怎么做?

首先把場(chǎng)景中的玩家、NPC 等都抽象成一樣的對(duì)象。同時(shí)將場(chǎng)景打上合適大小網(wǎng)格(比如一格 100 米為邊長(zhǎng),這取決于你允許的玩家視野),將每個(gè)格子也看成一個(gè)對(duì)象。

每個(gè)對(duì)象都帶有一個(gè)(或多個(gè))事件隊(duì)列。

對(duì)于格子對(duì)象來說,事件只記錄有別的對(duì)象來到這個(gè)格子,以及一個(gè)對(duì)象離開格子。

玩家對(duì)象的事件隊(duì)列則記錄這個(gè)對(duì)象自己做了什么動(dòng)作,收到了什么傷害,增加或減少了什么 buf 等等。

你的場(chǎng)景應(yīng)該是以某個(gè)心跳周期(通常不會(huì)超過 10Hz)來工作的,也就是游戲服務(wù)器上,所有對(duì)象的變化都是離散的。

所有的攻擊、移動(dòng)、技能都會(huì)以事件的方式,加上時(shí)間戳放到所屬對(duì)象的事件隊(duì)列中。

客戶端的查詢協(xié)議中的來說只有兩種:

  1. 查詢一個(gè)對(duì)象的當(dāng)前狀態(tài)以及該對(duì)象最新事件的時(shí)間戳。

  2. 查詢一個(gè)對(duì)象從某個(gè)時(shí)間戳開始,以后發(fā)生的所有事件列表。

如果客戶端還不了解一個(gè)對(duì)象時(shí),它發(fā)起查詢 1 ;如果已經(jīng)了解了這個(gè)對(duì)象,發(fā)起查詢 2 。或者根據(jù)需要發(fā)起查詢 1 (例如曾經(jīng)查詢過,但很久都不關(guān)心了)

在查詢沒有回應(yīng)前,限制再次提起查詢的次數(shù)。

這樣總能保持對(duì)某個(gè)對(duì)象最新狀態(tài)的了解。

當(dāng)一個(gè)玩家進(jìn)入場(chǎng)景,他要做的:

  1. 查詢進(jìn)入點(diǎn)。

  2. 根據(jù)進(jìn)入點(diǎn)坐標(biāo),查詢所在格和周圍格的發(fā)起查詢。

  3. 根據(jù)周圍格的查詢,獲知了周圍存在的對(duì)象。然后分別對(duì)這些對(duì)象做進(jìn)一步查詢。作為 MMO 可能存在大量的對(duì)象,通常篩選一部分就夠了。

  4. 一旦感興趣的對(duì)象走遠(yuǎn),就不再監(jiān)視它;這點(diǎn)不必依賴格子對(duì)象的狀態(tài)變化。所以格子的狀態(tài)反饋只需要有新增對(duì)象即可,而不必有對(duì)象離開的消息。所謂監(jiān)視一個(gè)對(duì)象,指在每次查詢回應(yīng)后,再次提起下一次查詢。有些對(duì)象,比如自己,需要響應(yīng)更及時(shí)。應(yīng)該同時(shí)向服務(wù)器發(fā)起多個(gè)查詢請(qǐng)求,這樣,服務(wù)器一旦判定你被攻擊或被某些事件改變,總能有可用的回應(yīng) session 供發(fā)送回應(yīng)包。同理,如果你在和人/ NPC 戰(zhàn)斗,那么對(duì)手也是重點(diǎn)關(guān)注對(duì)象。而周圍人跑來跑去、做了個(gè)動(dòng)作,可能你就不那么關(guān)心了。這個(gè)可以由客戶端來控制哪些該保持追蹤、哪些暫時(shí)不必理會(huì)。

  5. 最后關(guān)注自己(在場(chǎng)景中那個(gè)對(duì)象)。這樣如果有人攻擊你,你就能知道這個(gè)事件的發(fā)生。在攻擊發(fā)生后,還可以立刻去關(guān)注打你的這個(gè)人(如果之前沒有關(guān)注的話)。


可以做,且容易的做的優(yōu)化有:

  1. 事件合并。當(dāng)用戶請(qǐng)求某個(gè)時(shí)間戳之后的所有事件時(shí),有些事件是可以合并的,比如多次移動(dòng)可以合并成一個(gè);格子里一個(gè)對(duì)象進(jìn)進(jìn)出出,可以合并掉,并只回應(yīng)新增事件。

  2. 回應(yīng)包緩存。把事件列表序列化為網(wǎng)絡(luò)包有一定的開銷。有些信息肯定會(huì)有很多玩家來索要,你可以只做一次序列化工作,把數(shù)據(jù)緩存起來,等多個(gè)人來請(qǐng)求時(shí),直接回應(yīng)給他,省去了將信息反復(fù)序列化的流程。

  3. 多查詢合并。查詢多個(gè)格子的時(shí)候,可以合并在同一個(gè)請(qǐng)求中,這樣,對(duì)象在臨近格子間的移動(dòng)消息可能就被合并掉了。

從協(xié)議層,可以允許一次提起對(duì)很多對(duì)象的查詢請(qǐng)求,它們的查詢 session 一定是連續(xù)的,所以不必逐個(gè)編碼而只需要給個(gè)區(qū)間就夠了;同時(shí)也不妨礙單獨(dú)回應(yīng)。在上面的查詢約定中,如果發(fā)現(xiàn)時(shí)間戳之后到當(dāng)下,對(duì)象事件列表中若沒有事件,服務(wù)器是不回應(yīng)的。

例如,如果你來到一個(gè)無人區(qū),對(duì)所在格做了一次查詢,除了你自己外,沒有其它對(duì)象;你若再次查詢,結(jié)果不會(huì)有變化,所以服務(wù)器會(huì)掛起你的請(qǐng)求,直到附近有新對(duì)象出現(xiàn)。


由于請(qǐng)求和回應(yīng)是一一對(duì)應(yīng)的,所以不用擔(dān)心比單純的數(shù)據(jù)推送(訂閱模式)多出太多不必要的流量。

關(guān)于怎樣只基于請(qǐng)求回應(yīng)模式實(shí)現(xiàn)MMO級(jí)別的場(chǎng)景服務(wù)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI