騰訊QQGame游戲同時(shí)在線的玩家數(shù)量極其龐大,為了方便組織玩家組隊(duì)游戲,騰訊設(shè)置了大量游戲室(房間),玩家可以選擇進(jìn)入屬意的房間,并在此房間內(nèi)找到可以加入的游戲組(牌桌、棋盤等)。玩家選擇進(jìn)入某個(gè)房間時(shí),必須確保此房間當(dāng)前人數(shù)未滿(通常上限為400),否則進(jìn)入步驟將會(huì)失敗。玩家在登入QQGame后,會(huì)從服務(wù)器端獲取某類游戲下所有房間的當(dāng)前人數(shù)數(shù)據(jù),玩家可以據(jù)此找到未滿的房間以便進(jìn)入。
如上篇所述的原因,如果待進(jìn)入房間的人數(shù)接近上限時(shí),玩家的進(jìn)入請求可能失敗,這是因?yàn)榉?wù)器在收到此進(jìn)入請求之前可能有若干其他玩家也請求進(jìn)入這個(gè)房間,造成房間人數(shù)達(dá)到上限。
這一問題是無法通過上篇所述調(diào)整協(xié)作分配的方法來解決的,這是因?yàn)椋阂M(jìn)入的房間是由玩家來指定的,無法在服務(wù)器端完成此項(xiàng)工作,游戲軟件必須將服務(wù)器端所維護(hù)的所有房間人數(shù)數(shù)據(jù)復(fù)制到玩家的客戶端,并讓玩家在界面上看到這些數(shù)據(jù),以便進(jìn)行選擇。
這樣,上篇所述的客戶端與服務(wù)器端協(xié)作分配原則(誰掌握數(shù)據(jù),誰干活),還得加上一些限制條件,并讓位于另一個(gè)所謂"用戶驅(qū)動(dòng)客戶端行為"原則--如果某個(gè)功能的執(zhí)行是由用戶來推動(dòng)的,則這個(gè)功能的實(shí)現(xiàn)應(yīng)當(dāng)放在客戶端(或者至少由客戶端來控制整個(gè)協(xié)作),并且客戶端必須持有此功能所依賴相關(guān)數(shù)據(jù)的副本,這個(gè)副本應(yīng)當(dāng)盡量與服務(wù)器端的源保持同步。注意:點(diǎn)擊圖片可以放大觀看
圖一"進(jìn)入房間"失敗示意
QQGame還存在一個(gè)明顯的不足,就是:玩家如果在游戲一段時(shí)間后,離開了某個(gè)房間,并且想進(jìn)入其它房間,這時(shí)QQGame并不會(huì)刷新所有房間的當(dāng)前人數(shù),造成玩家據(jù)此信息所選的待進(jìn)入房間往往實(shí)際上人數(shù)已滿,使得進(jìn)入步驟失敗。筆者碰到的最糟情形是重復(fù)3、4次以上,才最后成功進(jìn)入另外某個(gè)房間。此缺陷其實(shí)質(zhì)是完全放棄了客戶端數(shù)據(jù)副本與服務(wù)器端的源保持同步的原則。
實(shí)際上,QQGame的開發(fā)者有非常充分的理由來為此缺陷的存在進(jìn)行辯護(hù):QQGame同時(shí)在線的用戶數(shù)超過百萬甚至千萬數(shù)量級,如果所有客戶端要實(shí)時(shí)(所謂實(shí)時(shí),就玩家的體驗(yàn)容忍度而言,可以定為不超過1秒的延遲)地從服務(wù)器端獲取更新數(shù)據(jù),那么最終只有一個(gè)結(jié)果--系統(tǒng)徹底崩潰。
設(shè)想一下每秒千萬次請求的吞吐量,以普通服務(wù)器每秒上百個(gè)請求的處理能力(這個(gè)數(shù)據(jù)是根據(jù)服務(wù)請求處理過程可能涉及到I/O操作來估值的,純內(nèi)存處理的情形可能提高若干數(shù)量級),需要成千上萬臺(tái)服務(wù)器組成集群方能承受(高可用性挑戰(zhàn));而隨著玩家不斷地進(jìn)入或退出游戲房間,相關(guān)數(shù)據(jù)一直在快速變化中,
正向來看,假設(shè)有一臺(tái)中心服務(wù)器持有這些數(shù)據(jù),那么需要讓成千上萬臺(tái)服務(wù)器與中心保持這些動(dòng)態(tài)數(shù)據(jù)的實(shí)時(shí)同步(數(shù)據(jù)一致性挑戰(zhàn));
相對應(yīng)的,逆向來看,玩家進(jìn)入房間等請求被分配給不同的服務(wù)器來處理,一旦玩家進(jìn)入房間成功則對應(yīng)服務(wù)器內(nèi)的相關(guān)數(shù)據(jù)被改變,那么假定中的中心服務(wù)器就需要實(shí)時(shí)匯集所有工作服務(wù)器內(nèi)發(fā)生的數(shù)據(jù)變動(dòng)(數(shù)據(jù)完整性挑戰(zhàn))。
同時(shí)處理上萬臺(tái)服務(wù)器的數(shù)據(jù)同步,這需要什么樣的中心服務(wù)器呢?即使有這樣的超級服務(wù)器存在,那么Internet網(wǎng)較大的(而且不穩(wěn)定的)網(wǎng)絡(luò)通訊延遲又怎么解決呢?
對于軟件缺陷而言,可以在不同的層面來加以解決--從設(shè)計(jì)、到需求、甚至是直接在業(yè)務(wù)層面來解決(例如,08年北京奧運(yùn)會(huì)網(wǎng)上購票系統(tǒng),為了解決訂票請求擁塞而至系統(tǒng)崩潰的缺陷,最后放棄了原先"先到先得"的購票業(yè)務(wù)流程,改為:用戶先向系統(tǒng)發(fā)訂票申請,系統(tǒng)只是記錄下來而不進(jìn)行處理,而到了空閑時(shí),在后臺(tái)隨機(jī)抽選幸運(yùn)者,為他們一一完成訂票業(yè)務(wù))。當(dāng)然解決方案所處的層面越高,可能就越讓人不滿意。
就上述進(jìn)入房間可能遭遇失敗的缺陷而言,最簡便的解決方案就是:在需求層面調(diào)整系統(tǒng)的操作方式,即增加一個(gè)類似上篇所述"自動(dòng)快速加入游戲"的功能--"自動(dòng)進(jìn)入房間"功能。系統(tǒng)在服務(wù)器端為玩家找到一個(gè)人數(shù)較多又未滿的房間,并嘗試進(jìn)入(注意,軟件需求是由用戶的操作目標(biāo)所驅(qū)動(dòng)的,玩家在此的目標(biāo)就是盡快加入一個(gè)滿意的游戲組,因此由系統(tǒng)來替代玩家選擇目標(biāo)房間同樣符合相關(guān)目標(biāo))。而為了方便玩家手工選擇要進(jìn)入的房間,則應(yīng)當(dāng)增加一個(gè)"刷新當(dāng)前各房間人數(shù)"的功能。另外,還可以調(diào)整房間的組織模式,例如以地域?yàn)閱挝粊韯澐址块g,像深圳(長城寬帶)區(qū)房間1、四川(電信)房間3、北美區(qū)房間1等,在深圳上網(wǎng)的玩家將被系統(tǒng)引導(dǎo)而優(yōu)先進(jìn)入深圳區(qū)的房間。
不管怎樣,解決軟件缺陷的王道還是在設(shè)計(jì)層面。要解決上述缺陷,架構(gòu)設(shè)計(jì)師就必須同時(shí)面對高可用、數(shù)據(jù)一致性、完整性等方面的嚴(yán)峻挑戰(zhàn)。
在思考相關(guān)解決方案時(shí),我們將應(yīng)用若干與高性能服務(wù)器集群架構(gòu)設(shè)計(jì)相關(guān)的一些重要原則。首先是"分而治之"原則,即將大量客戶端發(fā)出的服務(wù)請求進(jìn)行適當(dāng)?shù)膭澐郑ɡ纾袕纳钲陂L城寬帶上網(wǎng)的玩家所發(fā)出的服務(wù)請求分為一組),分別分配給不同的服務(wù)器(例如,將前述服務(wù)請求分組分配給放置于深圳數(shù)據(jù)中心的服務(wù)器)來加以處理。對于QQGame千萬級的并發(fā)服務(wù)請求數(shù)而言,采用Scale Up向上擴(kuò)展,即升級單個(gè)服務(wù)器處理能力的方式基本上不予考慮(沒有常規(guī)的主機(jī)能處理每秒上千萬的請求)。唯一可行的,只有Scale Out向外擴(kuò)展,即利用大量服務(wù)器集群做負(fù)載均衡的方式,這實(shí)質(zhì)上就是"分而治之"原則的具體應(yīng)用。點(diǎn)擊圖片可以放大
圖二 分而治之"下的QQGame游戲服務(wù)集群部署
然而,要應(yīng)用"分而治之"原則進(jìn)行Scale Out向外擴(kuò)展,還依賴于其它的條件。如果各服務(wù)器在處理被分配的服務(wù)請求時(shí),其行為與其它服務(wù)器的行為結(jié)果產(chǎn)生交叉(循環(huán))依賴,換句話講就是共享了某些數(shù)據(jù)(例如,服務(wù)器A處理客戶端a發(fā)來的進(jìn)入房間#n請求,而同時(shí),服務(wù)器B也在處理客戶端b發(fā)來的進(jìn)入房間#n請求,此時(shí)服務(wù)器A與B的行為存在循環(huán)依賴--因?yàn)閮烧咭瑫r(shí)訪問房間#n的數(shù)據(jù),這一共享數(shù)據(jù)會(huì)造成兩者間的循環(huán)依賴),則各服務(wù)器之間必須確保這些共享數(shù)據(jù)的一致完整性,否則就可能發(fā)生邏輯錯(cuò)誤(例如,假定房間#n的人數(shù)差一個(gè)就滿了,服務(wù)器A與B在獨(dú)自處理的情況下,將同時(shí)讓客戶端a與b的進(jìn)入請求成功,于是房間#n的最終人數(shù)將超出上限)。
而要做到此點(diǎn),各服務(wù)器的處理進(jìn)程之間就必須保持同步(實(shí)際上就是排隊(duì)按先后順序訪問共享數(shù)據(jù),例如:服務(wù)器A先處理,讓客戶端a進(jìn)入房間成功,此時(shí)房間#n滿員;此后服務(wù)器B更新到房間#n滿的數(shù)據(jù),于是客戶端b的進(jìn)入請求處理結(jié)果失?。?,這樣,原來將海量請求做負(fù)載均衡的意圖就徹底失敗了,多臺(tái)服務(wù)器的并發(fā)處理能力在此與一臺(tái)實(shí)質(zhì)上并沒有區(qū)別。
由此,我們導(dǎo)出了另外一個(gè)所謂"處理自治"(或稱"行為獨(dú)立")的原則,即所有參與負(fù)載均衡的服務(wù)器,其處理對應(yīng)服務(wù)請求的行為應(yīng)當(dāng)不循環(huán)依賴于其它服務(wù)器,換句話講,就是各服務(wù)器的行為相對獨(dú)立(注意:在這里,非循環(huán)依賴是允許的,下文中我們來分析為什么)。
由此可見,簡單的負(fù)載均衡策略對于QQGame而言是解決不了問題的。我們必須找到一種途徑,使得在使用大量服務(wù)器進(jìn)行"分而治之"的同時(shí),同時(shí)有確保各個(gè)服務(wù)器"處理自治"。此間的關(guān)鍵就在于"分而治之"的"分"字上。前述將某個(gè)地域網(wǎng)段內(nèi)上網(wǎng)的玩家所發(fā)出的服務(wù)請求分到一組,并分配給同一服務(wù)器的做法,其目的不外乎是盡可能地減少網(wǎng)絡(luò)通訊延遲帶來的負(fù)面影響。但它不能滿足"處理自治"的要求,為了確保自治,應(yīng)當(dāng)讓同一臺(tái)服務(wù)器所處理的請求本身是"自治"(準(zhǔn)確的說法是"自閉包"Closure)的。同一臺(tái)服務(wù)器所處理的所有請求組成一個(gè)服務(wù)請求集合,這個(gè)集合如果與其它任何與其無交集的(請求)集合(包含此集合的父集合除外)不循環(huán)依賴,則此服務(wù)請求集合是"自閉包"的,而處理此請求集合的服務(wù)器,其"行為獨(dú)立"。
我們可以將針對同一房間的進(jìn)入請求劃分到同一服務(wù)請求分組,這些請求相互之間當(dāng)然是存在循環(huán)依賴的,但與其它分組中的請求卻不存在循環(huán)依賴(本房間內(nèi)人數(shù)的變化不會(huì)影響到其它房間),而將它們都分配給同一服務(wù)器(不妨命名為"房間管理服務(wù)器",簡稱"房間服務(wù)器")后,那個(gè)服務(wù)器將是"處理自治"的。點(diǎn)擊圖片可以放大
圖三 滿足"處理自治"條件的QQ游戲區(qū)域"房間管理"服務(wù)部署
那么接下來要解決的問題,就是玩家所關(guān)注的某個(gè)游戲區(qū)內(nèi),所有房間當(dāng)前人數(shù)數(shù)據(jù)的實(shí)時(shí)更新問題。其解決途徑與上述的方法類似,我們還是將所有獲取同一區(qū)內(nèi)房間數(shù)據(jù)的服務(wù)請求歸為一組,并交給同一服務(wù)器處理。與上文所述場景不同的是,這個(gè)服務(wù)器需要實(shí)時(shí)匯集本區(qū)內(nèi)所有房間服務(wù)器的房間人數(shù)數(shù)據(jù)。我們可以讓每個(gè)房間服務(wù)器一旦發(fā)生數(shù)據(jù)變更時(shí),就向此服務(wù)器(不妨命名為"游戲區(qū)域管理服務(wù)器",簡稱"區(qū)服務(wù)器")推送一個(gè)變更數(shù)據(jù)記錄,而推送的數(shù)據(jù)只需包含房間Id和所有進(jìn)入的玩家Id(房間服務(wù)器還包含其它細(xì)節(jié)數(shù)據(jù),例如牌桌占位數(shù)據(jù))便可。
另外,由于一個(gè)區(qū)內(nèi)的玩家數(shù)可能是上十萬數(shù)量級,一個(gè)服務(wù)器根本承擔(dān)不了此種負(fù)荷,那么怎么解決這一矛盾呢?如果深入分析,我們會(huì)發(fā)現(xiàn),更新區(qū)內(nèi)房間數(shù)據(jù)的請求是一種數(shù)據(jù)只讀類請求,它不會(huì)對服務(wù)器狀態(tài)造成變更影響,因此這些請求相互間不存在依賴關(guān)系;這樣,我們可以將它們再任意劃分為更小的分組,而同時(shí)這些分組仍然保持"自閉包"特性,然后分配給不同的區(qū)服務(wù)器。多臺(tái)區(qū)服務(wù)器來負(fù)責(zé)同一區(qū)的數(shù)據(jù)更新請求,負(fù)載瓶頸被解決。
當(dāng)然,此前,還需將這些區(qū)服務(wù)器分為1臺(tái)主區(qū)服務(wù)器和n臺(tái)從屬區(qū)服務(wù)器;主區(qū)服務(wù)器負(fù)責(zé)匯集本區(qū)內(nèi)所有房間服務(wù)器的房間人數(shù)數(shù)據(jù),從屬區(qū)服務(wù)器則從主區(qū)服務(wù)器實(shí)時(shí)同步區(qū)房間數(shù)據(jù)副本。
更好的做法,則是如『圖五』所示,由房間服務(wù)器來充當(dāng)從屬區(qū)服務(wù)器的角色,玩家進(jìn)入某個(gè)房間后,在玩家進(jìn)入另外一個(gè)房間之前,其客戶端都將從此房間對應(yīng)的房間服務(wù)器來更新區(qū)內(nèi)房間數(shù)據(jù)。要注意的是,圖中房間服務(wù)器的數(shù)據(jù)更新利用了所謂的"分布式對象緩存服務(wù)"。
玩家進(jìn)入某個(gè)房間后,還要加入某個(gè)游戲組才能玩游戲。上篇所述的方案,是讓第一個(gè)加入某個(gè)牌桌的用戶,其主機(jī)自動(dòng)充當(dāng)本牌桌的游戲服務(wù)器;而其它玩家要加入此牌桌,其加入請求應(yīng)當(dāng)發(fā)往第一個(gè)加入的用戶主機(jī);此后開始游戲,其對弈過程將由第一個(gè)加入用戶的主機(jī)來主導(dǎo)執(zhí)行。
那么此途徑是否同樣也符合上述的前兩個(gè)設(shè)計(jì)原則呢?游戲在執(zhí)行的過程中,根據(jù)輸贏結(jié)果,玩家要加分或減分,同時(shí)還要記錄勝負(fù)場數(shù)。這些數(shù)據(jù)必須被持久化(比如在數(shù)據(jù)庫中保存下來),因此游戲服務(wù)器(『圖六』中的設(shè)計(jì),是由4個(gè)部署于QQ客戶端的"升級"游戲前臺(tái)邏輯執(zhí)行服務(wù),加上1個(gè)"升級"游戲后臺(tái)邏輯執(zhí)行服務(wù),共同組成一個(gè)牌桌的"升級"游戲服務(wù))在處理相關(guān)游戲執(zhí)行請求時(shí),將依賴于玩家游戲賬戶數(shù)據(jù)服務(wù)(『圖六』中的所謂"QQGame會(huì)話服務(wù)");
不過這種依賴是非循環(huán)的,即玩家游戲賬戶數(shù)據(jù)服務(wù)器的行為反過來并不依賴于游戲服務(wù)器。上文中曾提到,"處理自治"原則中非循環(huán)依賴是允許的。這里游戲服務(wù)器在處理游戲收盤請求時(shí),要調(diào)用玩家游戲賬戶數(shù)據(jù)服務(wù)器來更新相關(guān)數(shù)據(jù);因?yàn)椴煌婕业挠螒蛸~戶數(shù)據(jù)是相互獨(dú)立的,此游戲服務(wù)器在調(diào)用游戲賬戶數(shù)據(jù)服務(wù)器時(shí),邏輯上不受其它游戲服務(wù)器調(diào)用游戲賬戶數(shù)據(jù)服務(wù)器的影響,不存在同步等待問題;所以,游戲服務(wù)器在此能夠達(dá)成負(fù)載均衡的意圖。點(diǎn)擊圖片可以放大
圖四 存在"非循環(huán)依賴"的QQ游戲客戶端P2P服務(wù)與交互邏輯部署
不過,在上述場景中,雖然不存在同步依賴,但是性能依賴還是存在的,游戲賬戶數(shù)據(jù)服務(wù)器的處理性能不夠時(shí),會(huì)造成游戲服務(wù)器長時(shí)間等待。為此,我們可以應(yīng)用分布式數(shù)據(jù)庫表水平分割的技術(shù),將QQ玩家用戶以其登記的行政區(qū)來加以分組,并部署于對應(yīng)區(qū)域的數(shù)據(jù)庫中(例如,深圳的玩家數(shù)據(jù)都在深圳的游戲賬戶數(shù)據(jù)庫中)。
點(diǎn)擊圖片可以放大
圖五 滿足"自閉包"條件的QQ分布式數(shù)據(jù)庫(集群)部署
實(shí)際上,我們由此還可以推論出一個(gè)數(shù)據(jù)庫表水平分割的原則--任何數(shù)據(jù)庫表水平分割的方式,必須確保同一數(shù)據(jù)庫實(shí)例中的數(shù)據(jù)記錄是"自閉包"的,即不同數(shù)據(jù)庫實(shí)例中的數(shù)據(jù)記錄相互間不存在循環(huán)依賴。
總之,初步滿足QQGame之苛刻性能要求的分布式架構(gòu)現(xiàn)在已經(jīng)是初具雛形了,但仍然有很多涉及性能方面的細(xì)節(jié)問題有待解決。例如,Internet網(wǎng)絡(luò)通訊延遲的問題、服務(wù)器之間協(xié)作產(chǎn)生的性能瓶頸問題等等。筆者將在下篇中繼續(xù)深入探討這些話題。
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9123瀏覽量
85324 -
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3794瀏覽量
64360
原文標(biāo)題:從騰訊QQgame高性能服務(wù)器集群架構(gòu)看分布式架構(gòu)設(shè)計(jì)原則
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論