游戲服務(wù)器設(shè)計(jì)的相關(guān)內(nèi)容
作者Blog: http://blog.csdn.net/lfhfut
MSN: beyondlimit2001@hotmail.com
我不得不承認(rèn),我的能力不足以寫出一個(gè)100%不會(huì)宕機(jī)的游戲服務(wù)器程序,這也不能全怪我的能力太弱,誰讓咱國(guó)內(nèi)網(wǎng)游玩家數(shù)量龐大,哪個(gè)游戲剛上線時(shí)沒有擠的爆滿過?還有些或是獵奇,或是謀私的個(gè)人和組織,在制造著千奇百怪,匪夷所思的數(shù)據(jù)包及操作流程來試探你的服務(wù)器。這些都曾是我在服務(wù)器宕機(jī)后向老板開脫的理由。
當(dāng)WOW終于來到中國(guó)時(shí),我一邊欣喜著終于可以在艾澤拉斯的大陸上自由翱翔,一邊卻咒罵著9C的破服務(wù)器,動(dòng)不動(dòng)就宕機(jī)。當(dāng)然,身為游戲程序設(shè)計(jì)師的我明知道,這大部分的錯(cuò)誤都不應(yīng)歸罪于代理商9C,但是,誰讓blizzard是我心目中的神,誰又讓W(xué)OW成為我游戲制作的教科書呢。好吧,我知道上面這段極力追捧blizzard跟WOW的話可能早已讓你惡心連連,不堪入目了,對(duì)不起,忘了這一節(jié),讓我們繼續(xù)。
服務(wù)器宕機(jī)后都發(fā)生了些什么?
顯然的,宕機(jī)后玩家會(huì)罵,就像我在玩WOW時(shí)那樣,罵游戲公司,罵老板,罵GM。非常抱歉,我們可愛的玩家們似乎并不清楚,這個(gè)時(shí)候最該罵的其實(shí)是我們這些程序員們。長(zhǎng)久的遺忘被我們當(dāng)成了包容,以至于游戲程序員在公司里都養(yǎng)成了趾高氣揚(yáng),不可一世的壞毛病:看吧,策劃們,你們做的太爛了,數(shù)值不平衡,玩法沒新意,只會(huì)照抄WOW跟大菠蘿,能怪玩家罵你們嗎?運(yùn)營(yíng)不得力,買服務(wù)器的錢不知道去了哪里,游戲里卡的要死,偶爾辦個(gè)活動(dòng)還沒半點(diǎn)吸引力,能不被玩家罵你是無良運(yùn)營(yíng)商嗎?GM們能不天天被罵家指著罵嗎?……呃,又扯遠(yuǎn)了。
趕緊先把服務(wù)器重啟吧。老板正站在你的身后,一臉愁容,雖然暫時(shí)還沒有發(fā)作,但看得出來:老板很生氣,后果很嚴(yán)重!
玩家們很快又回來了,不得不為玩家們的毅力和執(zhí)著精神而感動(dòng),更為自己的錯(cuò)誤而愧疚,凌晨時(shí)分,服務(wù)器啟了又宕,宕了又啟,如此反復(fù),可熱情的玩家們依然陪著我在折騰。哦,當(dāng)年安其拉開門的時(shí)候,我也曾這樣折騰過。
這個(gè)時(shí)候不是你一個(gè)人在戰(zhàn)斗。GM們?cè)诿β档靥幚碇婕也粩啻騺淼耐对V電話:剛買的裝備在宕機(jī)后消失了;花光了身上所有材料合成的武器回檔了,但材料卻沒有還給我……數(shù)據(jù)庫維護(hù)組的同事們也在緊張的恢復(fù)著數(shù)據(jù),盡可能的將玩家的損失減到最少。
真是一件令人沮喪的事。
真的該試著做點(diǎn)什么了吧!
既然我們非常不愿意看到宕機(jī)的情況發(fā)生,但又無法100%保證寫出來的服務(wù)器程序一定不會(huì)出錯(cuò),那我們就在當(dāng)機(jī)發(fā)生后的搶救措施上花點(diǎn)功夫,讓玩家的損失不至于太大,也讓我們的維護(hù)人員少些壓力吧。
一個(gè)最簡(jiǎn)單也最有效的做法是為每一臺(tái)服務(wù)器都配備物理冗余,同步更新冗余服務(wù)器上的狀態(tài),當(dāng)宕機(jī)發(fā)生時(shí),立即將處理切換到后備服務(wù)器上。只是,物理冗余的代價(jià)太大,從成本方面考慮,老板可能不大愿意點(diǎn)頭。
既然不能做硬冗余,那就再來考慮軟的吧。
如果只是簡(jiǎn)單的啟動(dòng)冗余進(jìn)程,其實(shí)是換湯不換藥的做法。原來能跑1000人的服務(wù)器,由于同時(shí)運(yùn)行了兩個(gè)相同的進(jìn)程,使得CPU和內(nèi)存開銷都翻了倍,結(jié)果是只能跑500人了。還是要加服務(wù)器。
看來只能更深一層,從架構(gòu)設(shè)計(jì)上來動(dòng)手了。
假設(shè)我們的游戲世界是由多個(gè)獨(dú)立場(chǎng)景構(gòu)成的,那么在實(shí)現(xiàn)上我們可以讓這些場(chǎng)景在進(jìn)程上也獨(dú)立,這樣做的好處是可以使得一個(gè)場(chǎng)景的宕機(jī)不會(huì)影響到其他場(chǎng)景的正常運(yùn)行。如果我們的游戲世界物理上沒有分隔,是一個(gè)無縫的大世界,我們也可以人為的將其分成多個(gè)獨(dú)立區(qū)域,所需要做的額外工作是處理好那些站在區(qū)域邊界附近的對(duì)象。事實(shí)上,現(xiàn)在的無縫大世界也都是這樣實(shí)現(xiàn)的。
有了這樣一個(gè)前提,我們?cè)賮砜催@個(gè)已宕掉的場(chǎng)景該如何處理。
還是老辦法,趕緊先把它拉起來吧。一個(gè)具體可行的方案是,由場(chǎng)景管理器,或者你也有可能叫它世界服務(wù)器,來監(jiān)視各個(gè)場(chǎng)景進(jìn)程的運(yùn)行狀態(tài),當(dāng)某個(gè)場(chǎng)景異常失去聯(lián)系時(shí),由管理器來將其重新啟動(dòng)。這里需要再花點(diǎn)心思的是,如何讓玩家數(shù)據(jù)正常地發(fā)送到新啟動(dòng)的場(chǎng)景進(jìn)程中,而且這個(gè)過程對(duì)于客戶端來說是透明的。 #p#page_title#e#
這個(gè)方案聽起來似乎不錯(cuò),只是,如果宕掉的是場(chǎng)景管理器進(jìn)程,那該怎么辦呢?
按照前面的描述,場(chǎng)景管理器可以看作是整個(gè)游戲世界的中心,它以一個(gè)指揮者的身份維護(hù)著游戲世界的有序運(yùn)行,所以它的宕機(jī)對(duì)整個(gè)游戲世界的影響也將會(huì)是巨大的。
有沒有什么辦法能夠使得場(chǎng)景管理器進(jìn)程再次啟動(dòng)后能夠恢復(fù)先前的狀態(tài)呢?
我們可以為管理器和場(chǎng)景進(jìn)程定義一套協(xié)議,使得管理器不僅能夠創(chuàng)建并恢復(fù)一個(gè)已有場(chǎng)景,而且場(chǎng)景管理器還能通過現(xiàn)有的場(chǎng)景進(jìn)程數(shù)據(jù)恢復(fù)出自己。
一個(gè)理論上可行的方案是,場(chǎng)景管理器與場(chǎng)景進(jìn)程間保持TCP長(zhǎng)連接,并以一定頻率進(jìn)行心跳聯(lián)系,任意一方發(fā)現(xiàn)聯(lián)系中斷或長(zhǎng)時(shí)間未收到心跳包后都會(huì)立即做出處理。
如果是管理器發(fā)現(xiàn)場(chǎng)景進(jìn)程失去聯(lián)系,那就啟動(dòng)新的場(chǎng)景,如前面所描述的那樣。如果是場(chǎng)景進(jìn)程發(fā)現(xiàn)管理器失去聯(lián)系,那就立即啟動(dòng)重連過程,直接再次連接上管理器,然后立即將自己當(dāng)前的狀態(tài)和負(fù)責(zé)的場(chǎng)景ID報(bào)告給管理器。管理器通過這些上報(bào)的數(shù)據(jù)就能恢復(fù)出游戲世界內(nèi)的場(chǎng)景對(duì)應(yīng)關(guān)系表,也就是恢復(fù)出了自己原來的狀態(tài)。
進(jìn)程是恢復(fù)出來了,可我們忘了最重要的內(nèi)容:數(shù)據(jù)。當(dāng)場(chǎng)景進(jìn)程宕機(jī)后,上面保存的玩家屬性數(shù)據(jù)也隨之丟失了,雖然我們能夠再次將這個(gè)場(chǎng)景創(chuàng)建出來,并把原來在這個(gè)場(chǎng)景內(nèi)的客戶端數(shù)據(jù)重新定向過來,但這些客戶端對(duì)應(yīng)的玩家對(duì)象的數(shù)據(jù)卻沒有了,游戲仍然無法繼續(xù)。
也許我們可以再做一點(diǎn)修改,把場(chǎng)景內(nèi)的玩家數(shù)據(jù)分離出來,保存到一個(gè)獨(dú)立的進(jìn)程上,比如,我們可以把這個(gè)進(jìn)程叫做數(shù)據(jù)服務(wù)器,或者數(shù)據(jù)中心之類的。一個(gè)隱含的要求是,數(shù)據(jù)服務(wù)器的邏輯實(shí)現(xiàn)非常簡(jiǎn)單,簡(jiǎn)單到你可以認(rèn)為它是絕對(duì)安全的,不會(huì)宕機(jī)。所以,保存在這里的玩家數(shù)據(jù)也就是絕對(duì)安全的。
讓我們?cè)谶@個(gè)問題上稍微再深入一點(diǎn)。
場(chǎng)景進(jìn)程上每次執(zhí)行玩家的游戲邏輯時(shí)都要異步地到數(shù)據(jù)服務(wù)器上來存取數(shù)據(jù),這個(gè)開銷可能太大,而且會(huì)使得一些游戲邏輯的實(shí)現(xiàn)變的很復(fù)雜,那么,把一些會(huì)頻繁使用到的數(shù)據(jù)直接保存在場(chǎng)景進(jìn)程中,當(dāng)數(shù)據(jù)發(fā)生改變時(shí)同步更新到數(shù)據(jù)服務(wù)器上,這樣可能會(huì)比較容易接受。
老板全都滿意了嗎?
從理論上來說,我們已經(jīng)解決了場(chǎng)景進(jìn)程宕機(jī)和管理器宕機(jī)后的狀態(tài)恢復(fù)問題,并且在場(chǎng)景恢復(fù)后也不會(huì)因?yàn)閬G失了玩家數(shù)據(jù)而無法繼續(xù)進(jìn)行游戲,而且,只要處理得當(dāng),這個(gè)過程對(duì)客戶端來說可以是完全透明的,也就是玩家根本不知道服務(wù)器上有個(gè)進(jìn)程意外結(jié)束,我們做了這么多的工作來將它恢復(fù)了。
事實(shí)上,這個(gè)過程的透明也是必須的,我們并不需要嚷嚷著告訴我們的用戶,也就是玩家,我們做了多少多少事情來讓你玩的更順暢,又花了多少多少精力來解決因?yàn)榉?wù)器宕機(jī)而引起的麻煩,對(duì)于最終的用戶來說,他只需要享受最好的服務(wù)。閑話少說,讓我們繼續(xù)。
真的已經(jīng)完全解決了所有問題嗎?
想象這樣一個(gè)場(chǎng)景:我?guī)е鴰讉€(gè)剛剛降臨到艾澤拉斯大陸的伙伴沖向了艾爾文森林,去開荒霍格!正在霍格只剩下一絲血的時(shí)候,服務(wù)器稍稍卡了一下,等我緩過神來,面前的霍格驟然消失,地上也不見尸體。找了一圈,它正在出生點(diǎn)搖頭晃腦,也在四處張望,但頭頂上的血條分明是,滿血!
怎么回事?
處理這張地圖的場(chǎng)景進(jìn)程意外結(jié)束了,服務(wù)器的宕機(jī)處理機(jī)制很快地恢復(fù)了這個(gè)場(chǎng)景進(jìn)程,并且把我的客戶端數(shù)據(jù)重新定向到了新場(chǎng)景。只是,事情并不是一切都完美。因?yàn)檫@個(gè)場(chǎng)景是完全重新創(chuàng)建的,這意味著所有的怪物也是重新創(chuàng)建并被擺放到了初始位置,所以,只剩下一絲血的霍格碰上了好運(yùn)氣……
類似的還有,正在護(hù)送NPC返回營(yíng)地,在稍微停頓了一會(huì)兒之后,NPC又重新回到了原來的地方,等等。
雖然這比起最初的“客戶端被迫斷開連接,服務(wù)器端數(shù)據(jù)丟失”要進(jìn)步了許多,但會(huì)給我工資的老板仍然可能不太滿意,他希望,霍格應(yīng)該還在我的面前,而且只有一絲血,那個(gè)跟著我的NPC也應(yīng)該還在我旁邊…… #p#page_title#e#
我要是不能說服老板,這是“根本不可能完成的任務(wù)!”,那也就只能坐下來再試一試。
也許,可以考慮將所有對(duì)象的數(shù)據(jù)都保存到數(shù)據(jù)服務(wù)器上,當(dāng)然,這要求每個(gè)怪物都跟玩家一樣,有一個(gè)唯一ID,這一點(diǎn)實(shí)現(xiàn)起來可能會(huì)有些麻煩。
再不然,為對(duì)象提供一個(gè)從已有的內(nèi)存數(shù)據(jù)構(gòu)造的方法,這樣便可以使用共享內(nèi)存來保存現(xiàn)場(chǎng)數(shù)據(jù),再從共享內(nèi)存中恢復(fù)出原來的對(duì)象。理論上來說,這個(gè)方法是可行的,只是,這三十多個(gè)字的文字描述要用C++來實(shí)現(xiàn)也可能將會(huì)是一項(xiàng)極大的挑戰(zhàn),所以,這也僅只是可供參考的一個(gè)嘗試方案。
我想,我們走的夠遠(yuǎn)了
讓我們先暫停一會(huì)兒,回過頭來看一看最初的目的。其實(shí)我們想要的只是盡可能的讓服務(wù)器進(jìn)程不要宕機(jī),如果實(shí)在是沒有辦法,就盡可能的讓宕機(jī)后的玩家損失比較小,不需要我們做大量的工作去做善后處理。
很簡(jiǎn)單的需求,似乎我們糾纏的有些過頭了。
寫出能夠穩(wěn)定運(yùn)行的程序是對(duì)程序員的最基本要求,如果一個(gè)程序連穩(wěn)定性都不具備,那根本都不用再去考慮功能啊、擴(kuò)展啊等其他標(biāo)準(zhǔn)了。但是,正如我最開始所說的,沒有一個(gè)人能夠100%保證他寫出來的服務(wù)器程序是絕對(duì)不會(huì)崩潰的。我們所能要求的只是盡可能的仔細(xì),盡可能的多一些必要的測(cè)試,離安全盡可能的更近一步。
剩下的就是在宕機(jī)后如何降低損失的問題了。
對(duì)于一般的MMOG來說,玩家在進(jìn)入游戲時(shí)會(huì)從數(shù)據(jù)庫中將該玩家的所有相關(guān)數(shù)據(jù)讀到內(nèi)存,以便快速的進(jìn)行游戲邏輯的處理,而在玩家下線時(shí)再將數(shù)據(jù)的改動(dòng)存回?cái)?shù)據(jù)庫。
顯然的,當(dāng)服務(wù)器進(jìn)程出現(xiàn)意外宕機(jī)時(shí),內(nèi)存中所有的數(shù)據(jù)都丟失了,這也就造成了玩家數(shù)據(jù)的回檔,而且玩家在游戲中呆的時(shí)間越長(zhǎng),回檔的損失就越大。所以,一個(gè)被廣泛采用的做法是為玩家數(shù)據(jù)實(shí)現(xiàn)一種定時(shí)存盤的機(jī)制,就像現(xiàn)在大多數(shù)的單機(jī)游戲一樣,AutoSave。比如,每5分鐘自動(dòng)為玩家存一次盤,這樣就可以使得回檔的最大損失控制在5分鐘以內(nèi)。
另外,對(duì)于一些重要數(shù)據(jù)的變動(dòng),比如玩家花大量游戲貨幣購買了一件貴重的武器裝備,這時(shí)可將玩家數(shù)據(jù)立即做一次存盤操作,這也將有效的減少玩家的重大損失。
聽起來這是一項(xiàng)不錯(cuò)的技術(shù),在意外宕機(jī)的時(shí)候最多只回檔5分鐘,而且還沒有貴重物品的損失,玩家應(yīng)該是可以接受的吧。
我已經(jīng)聽到了數(shù)據(jù)庫維護(hù)員的咆哮
“數(shù)據(jù)庫已經(jīng)快要崩潰了,你就不能讓每秒需要執(zhí)行的SQL語句少一點(diǎn)嗎?”
“呃………”
我一直以為我們的數(shù)據(jù)庫非常強(qiáng)大,可以處理任何的數(shù)據(jù),唯一的缺點(diǎn)就是查詢速度比直接內(nèi)存讀取要慢很多。所以我使用了異步數(shù)據(jù)存取的方法,并且開啟了多個(gè)數(shù)據(jù)庫操作線程來并行的執(zhí)行我的請(qǐng)求,運(yùn)行的效果看起來還不錯(cuò)。
也許,我應(yīng)該來算一算,每秒種究竟丟了多少條操作請(qǐng)求給數(shù)據(jù)庫。
請(qǐng)?jiān)试S我再自私一回,我已經(jīng)很久沒有提到WOW了……
大概可信的數(shù)字是,WOW一組服務(wù)器的玩家數(shù)量在3000到5000之間,去掉最大的數(shù),再去掉最小的數(shù),最后的平均值是,4000吧,就算4000。
4000人在線,假設(shè)也是每5分鐘定時(shí)存盤一次,再假設(shè)所有玩家的存盤時(shí)間是平均分布的。這樣算下來,每秒種就會(huì)有67個(gè)玩家向數(shù)據(jù)庫發(fā)出存盤請(qǐng)求操作。
才67個(gè),數(shù)據(jù)庫維護(hù)組的同事就跟我說不堪重負(fù)了?笑話,這數(shù)據(jù)庫服務(wù)器是誰買的?
先別急,67是玩家數(shù),但是每個(gè)玩家的存盤請(qǐng)求不會(huì)只有一條SQL語句。
雖然每個(gè)游戲的內(nèi)容都各有差別,但是一款MMOG需要存入數(shù)據(jù)庫的數(shù)據(jù)少不了會(huì)有技能、物品、任務(wù)、寵物、好友、公會(huì)這些東西。取決于游戲的類型差異,每個(gè)游戲都會(huì)有自己的存盤方式,比如我可能會(huì)把所有的技能ID作為一條數(shù)據(jù)來存儲(chǔ),但是我也有可能把每個(gè)技能作為一條單獨(dú)的記錄來存儲(chǔ),這樣可以方便對(duì)技能附加數(shù)據(jù)的擴(kuò)展,等等。 #p#page_title#e#
但是,游戲中的物品存儲(chǔ)大概都是相同的,只能是一件(組)物品作為一條記錄來存儲(chǔ)。
而且,可以說游戲中存儲(chǔ)量最大的就是物品數(shù)據(jù)。算一算你的角色背包有多大,50格? 100格?還是200格?不要忘了銀行、擺攤位、裝備攔、寵物背包和郵箱這些地方也能放物品。并且,在游戲進(jìn)行過程中,玩家背包中物品數(shù)據(jù)的變動(dòng)也是相當(dāng)?shù)念l繁,不斷的有藥品被用掉,不斷地又有些小玩意兒被撿起來,不久后,它們又被賣給了NPC。
雖然你可以使用一些巧妙的比較算法來過濾掉那些實(shí)際上沒有發(fā)生變動(dòng)的物品更新,另外也不是所有的玩家物品數(shù)據(jù)變動(dòng)都很頻繁,但在實(shí)際運(yùn)營(yíng)中,尤其是當(dāng)玩家的背包格數(shù)都很多的時(shí)候,物品數(shù)據(jù)的存盤的確會(huì)成為一個(gè)很大的問題。
除了物品,還有玩家的基本屬性存盤,社會(huì)關(guān)系存盤等等,再加上全局公共數(shù)據(jù)的存盤,如公會(huì)數(shù)據(jù),拍賣行物品數(shù)據(jù),如果老板也要我在游戲中開上一家拍賣行的話。
這么一算下來,似乎是有些多了。
再一次的挑戰(zhàn)
具體的數(shù)字將取決于游戲的類型和設(shè)計(jì)的數(shù)據(jù)表結(jié)構(gòu)。
而數(shù)據(jù)庫服務(wù)器能承擔(dān)的每秒查詢數(shù)則取決于數(shù)據(jù)庫服務(wù)器的軟硬件配置情況。
但是一般來說,數(shù)據(jù)庫維護(hù)人員可能會(huì)告訴我,當(dāng)每秒執(zhí)行的SQL語句數(shù)達(dá)到1000條時(shí),數(shù)據(jù)庫服務(wù)器將會(huì)感受到明顯的壓力,我可能也會(huì)看到數(shù)據(jù)庫執(zhí)行隊(duì)列中的請(qǐng)求數(shù)一直在增長(zhǎng),也可能會(huì)看到數(shù)據(jù)庫服務(wù)器間歇性地拒絕響應(yīng),等等。
看起來我們又一次的面對(duì)到了巨大的打冷戰(zhàn)。
這個(gè)問題的起因是什么?我們不希望服務(wù)器進(jìn)程宕機(jī)時(shí)回檔太久,所以我們?cè)黾恿艘粋€(gè)玩家數(shù)據(jù)定時(shí)存盤的機(jī)制,結(jié)果卻導(dǎo)致了數(shù)據(jù)庫請(qǐng)求的驟然增多。
那再退回到這個(gè)起點(diǎn)處,將定時(shí)存盤的時(shí)間間隔延長(zhǎng)點(diǎn),比如10分鐘才存一次?數(shù)據(jù)庫的壓力會(huì)有緩解,但最初的問題卻又會(huì)有所暴露。真是個(gè)兩難的問題。
既想要玩家數(shù)據(jù)存盤間隔時(shí)間短一點(diǎn),又不想給數(shù)據(jù)庫造成的壓力太大。
同樣的需求似乎出現(xiàn)過很多回了:在中間加一層代理做緩沖。我們姑且稱這一層代理為數(shù)據(jù)庫代理服務(wù)器,它所要完成的工作是從場(chǎng)景進(jìn)程收集玩家的定時(shí)存盤請(qǐng)求數(shù)據(jù),再以一個(gè)低一點(diǎn)的頻率寫入到數(shù)據(jù)庫。
聽起來這又像是一個(gè)換湯不換藥的做法,寫入數(shù)據(jù)庫的時(shí)間間隔還是變長(zhǎng)了。但實(shí)際上在前面我們就曾經(jīng)描述過,如果服務(wù)器進(jìn)程不會(huì)出現(xiàn)意外的宕機(jī),玩家數(shù)據(jù)只需要在他上線時(shí)讀取,在他下線時(shí)寫入即可,中間添加的這些定時(shí)存盤過程完全只是為了防范宕機(jī)回檔所造成的巨大損失。
因?yàn)檫@個(gè)中間代理層的加入,我們把場(chǎng)景進(jìn)程宕機(jī)的隱患與數(shù)據(jù)丟失的后果隔離開來了,現(xiàn)在即使場(chǎng)景進(jìn)程宕機(jī),數(shù)據(jù)還在數(shù)據(jù)庫代理服務(wù)器上,當(dāng)然這里又隱含了一個(gè)條件:數(shù)據(jù)庫代理服務(wù)器需要足夠穩(wěn)定,不會(huì)在場(chǎng)景進(jìn)程之前先宕掉。事實(shí)上,因?yàn)檫@個(gè)代理進(jìn)程的工作是,我們完全有理由相信,這個(gè)進(jìn)程是非常穩(wěn)定的,那樣的話,多久時(shí)間才把緩存的數(shù)據(jù)真正寫入數(shù)據(jù)庫,就看你自己的喜好了。
該結(jié)束了吧
是否有些似曾相識(shí)的感覺?
沒錯(cuò),前面我們?cè)?jīng)描述過一個(gè)數(shù)據(jù)服務(wù)器,也是這樣說的。
所以,數(shù)據(jù)服務(wù)器,數(shù)據(jù)庫代理服務(wù)器可以合并到一起,來共同保證數(shù)據(jù)的安全。
再加上場(chǎng)景進(jìn)程與管理器進(jìn)程的恢復(fù)協(xié)議,讓服務(wù)器的重啟對(duì)玩家保持透明。
看起來這個(gè)晚上可以睡個(gè)安穩(wěn)覺。
確實(shí)可以結(jié)束了。