架构师必看-架构之美第15章伸缩性架构设计
? ? ? 在設(shè)計系統(tǒng)架構(gòu)時,一個比較有趣的問題就是確保系統(tǒng)在伸縮時的彈性。隨著越來越多的系統(tǒng)運(yùn)行在網(wǎng)絡(luò)上或在互聯(lián)網(wǎng)上提供訪問,伸縮性正變得越來越重要。對于這樣的系統(tǒng),如果你希望誤差的范圍在幾個數(shù)量級以內(nèi),那么容量規(guī)劃的想法顯然是荒謬的。如
果你架起一個網(wǎng)站,然后它火了,你可能會突然發(fā)現(xiàn)有幾百萬的用戶訪問你的站點(diǎn)。同樣容易出現(xiàn)的情況是,你架起了一個網(wǎng)站,卻發(fā)現(xiàn)沒有人感興趣,你投入的所有設(shè)備都閑置著,消耗著能源和管理成本,浪費(fèi)錢財(這同樣是一種災(zāi)難)。在網(wǎng)絡(luò)世界里,一個站點(diǎn)可以在幾分鐘內(nèi)從其中一種狀態(tài)轉(zhuǎn)變成另一種狀態(tài)。
? ? ? ?只要是將系統(tǒng)連接到網(wǎng)絡(luò)上,每個人都會遇到伸縮性問題,但是“大型多人在線游戲”(MMO)和虛擬世界特別關(guān)注這一點(diǎn)。這些系統(tǒng)必須具備伸縮性,以滿足大量的用戶。Web服務(wù)器的用戶常常讀取的是靜態(tài)的內(nèi)容,而且彼此之間沒有交互,但MMO中的玩家或虛擬世界中的居民則不同,他們既需要與所處的世界進(jìn)行交互(這改變了世界的基本信息),也需要彼此之間的交互。這些交互行為使得這類系統(tǒng)基礎(chǔ)設(shè)施的伸縮性問題變得更復(fù)雜,因為用戶與系統(tǒng)的交互幾乎是獨(dú)立的(除了那些不獨(dú)立的情況),而且不會讓世界的狀態(tài)改變太多。對于一個世界里的任意兩個參與者,他們在某個時刻進(jìn)行交互的幾率是非常小的。但是,幾乎所有玩家在所有時候都在與他人交互。結(jié)果是這種系統(tǒng)并行程度非常高,但只有少數(shù)的交互是互相依賴的。
? ? ? ?由于這些系統(tǒng)所培育起來的文化,MMO和虛擬世界的伸縮性問題進(jìn)一步復(fù)雜化了。MMO和虛擬世界都源自于視頻游戲產(chǎn)品。這是一種從PC游戲和游戲機(jī)游戲傳統(tǒng)中成長起來的文化,在這種傳統(tǒng)中,程序員會假定游戲運(yùn)行在一臺獨(dú)立的機(jī)器或游戲機(jī)上。在這樣的環(huán)境中,機(jī)器所有的資源都受游戲程序控制,程序的問題也限于單個用戶玩游戲的情況(實(shí)際上,缺陷或奇怪的行為常常會被認(rèn)為是游戲本身邏輯的一部分)。
? ? ? ? 這些游戲和編寫、出品、擴(kuò)展它們的公司,都屬于娛樂行業(yè)。編寫游戲的團(tuán)隊由一個出品人領(lǐng)導(dǎo),有劇本和背景故事。游戲的目標(biāo)是刺激、打動人,最重要的一點(diǎn),要好玩。可靠性很好,但不一定必需。可擴(kuò)展性是游戲的特性,讓游戲在升級時能夠加入新的故事情節(jié)和主題,但可擴(kuò)展性不是代碼的特性,不必讓代碼能以新的、不同的方式使用。
? ? ? ?在線游戲和虛擬世界的興起將這種文化帶入了一個新的環(huán)境,在這個環(huán)境中,需求與企業(yè)應(yīng)用開發(fā)者所面對的類似。多個用戶通過網(wǎng)絡(luò)在服務(wù)器上交互時,由于一個玩家的意外動作而導(dǎo)致的服務(wù)器崩潰將影響許多其他玩家。隨著這些世界發(fā)展出自己的經(jīng)濟(jì)(有些經(jīng)濟(jì)與現(xiàn)實(shí)世界的經(jīng)濟(jì)有關(guān)系),在線世界的穩(wěn)定性和一致性就超出了一個游戲的要求。隨著這些世界中玩家或居民的人數(shù)達(dá)到百萬級,伸縮的能力就成為了任何架構(gòu)的首要需求。
? ? ? Darkstar項目(本章后面將簡稱為Darkstar)是對這些游戲和虛擬世界創(chuàng)建者的需求挑戰(zhàn)的回答。這個項目由Sun公司實(shí)驗室的一個研究小組承擔(dān),它將在架構(gòu)的伸縮性領(lǐng)域不斷探索。這個項目特別有趣之處在于,它是針對MMO和虛擬世界的創(chuàng)建者,這些程序員與我們(作為系統(tǒng)設(shè)計者)所熟悉的那些程序員相比,有著非常不同的需求。得到的架構(gòu)看起來似乎很眼熟,但如果你仔細(xì)查看,會發(fā)現(xiàn)它的不同之處,它與你的經(jīng)驗有所不同。得到的架構(gòu)有著屬于它自己的美麗,同時它也是一堂實(shí)踐課,說明了不同的需求如何改變你所想到的構(gòu)建系統(tǒng)的方式。
3.2 背景
? ? ? ? 像一座建筑或一個城市的物理架構(gòu)一樣,系統(tǒng)的架構(gòu)必須適應(yīng)環(huán)境,利用該架構(gòu)創(chuàng)建的工件將存在于該環(huán)境之中。對于物理架構(gòu)來說,這個環(huán)境包括工作的歷史環(huán)境、它所處位置的氣候、本地工人的技能、可以獲得的建筑材料,以及建筑的使用意圖。對于軟件架構(gòu),這個環(huán)境不僅包括使用該架構(gòu)的應(yīng)用程序,也包括那些要使用該架構(gòu)的程序員,以及由此受到的系統(tǒng)約束。
? ? ? ?在創(chuàng)建Darkstar架構(gòu)時,我們(注1)意識到的第一件事就是所有針對伸縮性而設(shè)計的架構(gòu)都需要包含多臺機(jī)器。我們不清楚,就算是最大的大主機(jī)系統(tǒng)是否能夠滿足今天的一些在線游戲的要求(例如《魔獸世界》,據(jù)報道它有500萬注冊用戶,幾十萬的同時在線
用戶)。就算單臺機(jī)器能夠處理這種負(fù)載,我們也不能在一開始就假定游戲會取得如此成功,需要這樣的硬件投資。這在經(jīng)濟(jì)上是不可行的。這種應(yīng)用需要能夠從很小的系統(tǒng)開始,然后隨著用戶數(shù)的增長而增加處理能力,最后隨著大家對游戲興趣的衰退而降低處理能力。這與分布系統(tǒng)的特點(diǎn)相符,在分布式系統(tǒng)中,我們可以隨著請求增長而添加(合理的小)機(jī)器,當(dāng)請求下降時移走機(jī)器。所以我們從一開始就知道,總體架構(gòu)必須是一個分布式系統(tǒng)。
? ? ? ? 我們也知道系統(tǒng)利用了芯片架構(gòu)的當(dāng)前趨勢。MMO和虛擬世界(在較小程度上)曾經(jīng)針對伸縮性利用過摩爾定律。隨著處理器的速度倍增,可以創(chuàng)造的世界會在復(fù)雜度、豐富程度和互動性方面倍增。沒有其他計算領(lǐng)域像游戲世界這樣探索過處理器速度的增長所帶來的好處。為游戲而設(shè)計的個人計算機(jī)總是將CPU速度、內(nèi)存和圖形性能推向極致。游戲機(jī)更激進(jìn)地將這些方面推向極致,它們包含的圖形系統(tǒng)遠(yuǎn)遠(yuǎn)超過了高端工作站上的圖形系統(tǒng),整個機(jī)器完全是為了游戲玩家的特殊需要而打造的。
? ? ? ?芯片演進(jìn)方面最近的變化是從不斷增加的時鐘速度轉(zhuǎn)為實(shí)現(xiàn)多核處理器,這已經(jīng)對游戲中能做的事情產(chǎn)生了影響。新芯片的設(shè)計目標(biāo)不是將一件事做得更快,而是同時做多件事。如果在芯片上運(yùn)行的多項任務(wù)實(shí)際上可以同時執(zhí)行,那么在芯片層面上引入并發(fā)執(zhí)行將帶來更好的總體性能。在不改變時鐘速度的情況下,4核的芯片應(yīng)該能比單核的芯片多做3倍的事情。實(shí)際上,這種增長不是呈線性的,因為系統(tǒng)的其他一些部分沒有以同樣的方式實(shí)現(xiàn)并發(fā)。但是可以通過并發(fā)來實(shí)現(xiàn)系統(tǒng)總體性能的增長,而且制造這種并發(fā)的芯片比制造增加時鐘速度的芯片要容易得多。
? ? ? ?基于這一事實(shí),MMO和虛擬世界應(yīng)該是多核芯片和分布式系統(tǒng)的理想候選者。在MMO或虛擬世界中發(fā)生的大多數(shù)事情就像在真實(shí)世界中發(fā)生的大多數(shù)事情一樣,與該世界中發(fā)生的其他事情是無關(guān)的。玩家繼續(xù)他們的搜索或裝飾他們的房間。他們與怪物交戰(zhàn)或設(shè)計衣服。即使他們與該世界中的另一個玩家或居民發(fā)生交互,也只是與該世界的很少一部分居民發(fā)生交互。這正是令人為難的并行計算任務(wù)的特點(diǎn),也正是多核和多機(jī)系統(tǒng)應(yīng)該擅長處理的那種任務(wù)。
? ? ? ?盡管這些系統(tǒng)中的任務(wù)的并行度讓人為難,但為這樣的系統(tǒng)編程的程序員卻沒有接受過分布式計算或并發(fā)編程方面的訓(xùn)練,也沒有這方面的經(jīng)驗。這是極為微妙的領(lǐng)域,即使是在這個領(lǐng)域接受過訓(xùn)練的人和對這些技術(shù)相當(dāng)有經(jīng)驗的人也會感到困難。要讓大多數(shù)游戲程序員來開發(fā)高度并發(fā)的、分布式游戲服務(wù)器,就是要求他們做超出自己的專長和經(jīng)驗的事。
3.2.1 首要目標(biāo)
? ? ? ? ?這樣的背景為我們確立了該架構(gòu)的首要目標(biāo)。對伸縮性的需求表明,系統(tǒng)應(yīng)該是分布式的、并發(fā)的,但我們需要為游戲開發(fā)者提供簡單得多的編程模型。簡而言之,目標(biāo)就是游戲程序員應(yīng)該把該系統(tǒng)視為一臺單機(jī),運(yùn)行著一個線程,所有允許部署到多線程和多計算機(jī)上的機(jī)制都應(yīng)該由Darkstar項目的基礎(chǔ)設(shè)施來考慮。在一般的情況下,對應(yīng)用程序隱藏分布式和并發(fā)是不可能的。但MMO和虛擬世界不是一般的情況。我們試圖實(shí)現(xiàn)的這種隱藏,其代價就是必需一種非常特別的、嚴(yán)格限制的編程模型。幸運(yùn)的是,這種模型恰好非常適合游戲服務(wù)器和虛擬世界已經(jīng)采用的編程方式。
? ? ? ? ?Darkstar項目要求的一般編程模型是反應(yīng)式的,在這種編程模型中,游戲的服務(wù)器端寫成了事件監(jiān)聽器,監(jiān)聽客戶端生成的事件(客戶端就是游戲玩家使用的機(jī)器,通常是一臺PC或游戲機(jī))。如果檢測到事件,游戲服務(wù)器就應(yīng)該生成一項任務(wù),這個任務(wù)是一個短期的計算序列,包括操作虛擬世界中的信息,并與最初生成事件的客戶端或其他一些客戶端進(jìn)行通信。任務(wù)也可以由游戲服務(wù)器自己生成,要么是響應(yīng)某些內(nèi)部的變化,要么是周期性地根據(jù)時間來生成任務(wù)。在這種情況下,游戲服務(wù)器可以在游戲或虛擬世界中生成一些角色,這些角色是不受外部玩家控制的。
? ? ? ? 這種編程模型非常適合游戲和虛擬世界,但它也應(yīng)用于一些企業(yè)級的架構(gòu)中,如J2EE和Web服務(wù)。之所以需要創(chuàng)建一個不同于這些企業(yè)計算機(jī)制的架構(gòu),是因為MMO和虛擬世界存在的環(huán)境非常不一樣。這種環(huán)境幾乎剛好和經(jīng)典企業(yè)環(huán)境相反,這意味著如果你接受過企業(yè)環(huán)境方面的訓(xùn)練,你知道的所有事情在這個新世界中幾乎都是錯的。經(jīng)典的企業(yè)環(huán)境可以描述為一個“瘦”客戶端連接到一個“胖”服務(wù)器(這個服務(wù)器又常常連接到一個更“胖”的數(shù)據(jù)庫服務(wù)器)。服務(wù)器將保存客戶端需要的絕大部分信息,在最理想的情況下,客戶端內(nèi)存不多,沒有自己的硬盤,它是服務(wù)器的一個稱職的顯示設(shè)備,絕大多數(shù)真正的工作在服務(wù)器上完成。
3.2.2 游戲世界
? ? ? ? MMO和虛擬世界的環(huán)境始于一個非常胖的客戶端:它通常是頂級的PC、具有最強(qiáng)勁的CPU、很大的內(nèi)存,以及本身計算能力就很強(qiáng)的顯卡。它也可以是一臺游戲機(jī),專門為圖形密集的、高度交互的任務(wù)而設(shè)計。只要有可能,數(shù)據(jù)就會存放在這些客戶端,特別是那些不會改變的信息,如地理信息、材質(zhì)貼圖和規(guī)則集。服務(wù)器保持盡可能的簡單,通常只保存非常抽象的世界表示和其世界中的實(shí)體的表示。而且,服務(wù)器的設(shè)計目標(biāo)是盡可能少地進(jìn)行計算。絕大部分的計算留給了客戶端。服務(wù)器的真正工作是保存共享的世界真實(shí)狀態(tài),確保不同客戶端對世界的看法差異可以根據(jù)需要得到糾正。真實(shí)狀態(tài)需要由服務(wù)器來保存,因為控制客戶端的玩家很有興趣讓他們的表現(xiàn)變成最強(qiáng),所以可能會受到誘惑,根據(jù)他們的喜好修改共享的真實(shí)(如果他們可以)。在一般情況下,如果有可能,玩家就會作弊,所以服務(wù)器必須是共享真實(shí)的最終來源。
? ? ? ? MMO和虛擬世界的數(shù)據(jù)訪問模式也和企業(yè)中看到的情況有著很大的區(qū)別。企業(yè)中的一般經(jīng)驗法則是90%的數(shù)據(jù)訪問都是只讀的,大多數(shù)任務(wù)會讀取大量數(shù)據(jù),然后再改寫少量數(shù)據(jù)。在MMO和虛擬世界的環(huán)境中,大多數(shù)任務(wù)只訪問服務(wù)器上少量的狀態(tài)數(shù)據(jù),但在它們訪問的數(shù)據(jù)中,大約一半會被改寫。
3.2.3 延遲是敵人
? ? ? ? ?但是,這兩種環(huán)境中最大的不同要追溯到用戶所做的事情的不同。在企業(yè)環(huán)境中,目標(biāo)是管理業(yè)務(wù),如果總吞吐量得到改進(jìn),在處理中有一點(diǎn)延遲是可以接受的。在MMO和虛擬世界的環(huán)境中,目標(biāo)是開心,而延遲是開心的敵人。所以MMO或虛擬世界的基礎(chǔ)設(shè)施需要圍繞著盡可能限定延遲的需求來設(shè)計,即便以吞吐量為代價也在所不惜。在線游戲和虛擬世界顯然已經(jīng)找到了辦法來實(shí)現(xiàn)伸縮性,以應(yīng)對數(shù)量巨大的用戶。目前的方法可以分成兩大類。第一類實(shí)質(zhì)上是基于地理位置來實(shí)現(xiàn)的。游戲設(shè)計成包含一組不同的區(qū)域,每個區(qū)域運(yùn)行在一臺服務(wù)器上。它可能是虛擬世界的一個島或房間,也可能是在線游戲中的一個小鎮(zhèn)或山谷。游戲設(shè)計試圖讓每個區(qū)域無關(guān),限定地理區(qū)域的大小,這樣服務(wù)器不會因太多用戶進(jìn)入這個區(qū)域而擁塞。在實(shí)踐中,這樣的區(qū)域常常能實(shí)現(xiàn)自我限制,因為當(dāng)服務(wù)擁塞時,游戲就會變得響應(yīng)比較慢,趣味性下降。因此,玩家就會轉(zhuǎn)向更有趣的區(qū)域,這使得以前擁塞的區(qū)域人數(shù)減少,響應(yīng)時間得到改進(jìn)。
? ? ? ? 將不同地理區(qū)域分配給不同服務(wù)器來實(shí)現(xiàn)伸縮性的方法有一個問題,即必須在游戲編寫時決定哪些區(qū)域應(yīng)該放到一臺服務(wù)器上。雖然在游戲或虛擬世界中添加新的區(qū)域相當(dāng)容易,但是改變已經(jīng)分配給服務(wù)器的區(qū)域卻可能需要改動代碼。決定哪些區(qū)域組成一個伸縮性單位,這必須是開發(fā)工作的一部分。
? ? ? ? 第二種處理游戲或虛擬世界中擁塞區(qū)域的方法叫做分區(qū)(sharding)。一個分區(qū)是該區(qū)域的一份副本,運(yùn)行在它自己的服務(wù)器上,獨(dú)立于其他的分區(qū),它代表了游戲中相同的部分,即原來的區(qū)域。這樣,分區(qū)可能代表了某個房間或村莊的不同副本,允許成倍的玩
家進(jìn)入到世界的這個部分中。分區(qū)的缺點(diǎn)是它們不允許處于不同分區(qū)的玩家彼此之間進(jìn)行交互。隨著游戲和虛擬世界變成更多的社交體驗,而不僅僅是玩游戲,這種缺點(diǎn)就明顯了。玩家的目標(biāo)不只是要出現(xiàn)在虛擬世界中,而是要和他們的朋友(真實(shí)的和虛擬的)一起進(jìn)入虛擬世界。分區(qū)阻礙了這個目標(biāo)的實(shí)現(xiàn)。
? ? ? ? 因此,Darkstar架構(gòu)的另一個主要目標(biāo)就是支持隨時伸縮,同時不要求游戲邏輯受到伸縮的影響。這個架構(gòu)應(yīng)該支持游戲動態(tài)地響應(yīng)負(fù)載,而不是讓這種響應(yīng)成為游戲設(shè)計工作的一部分。
3.3 架構(gòu)
? ? ? ? Darkstar由一組獨(dú)立的服務(wù)構(gòu)成,這些服務(wù)可以在游戲或虛擬世界的服務(wù)器端的地址空間內(nèi)獲得。每個服務(wù)都定義為一個小的編程接口。盡管不是出于本意,但Darkstar項目提供的一些基本服務(wù)很像經(jīng)典操作系統(tǒng)的服務(wù),它們支持游戲或虛擬世界的服務(wù)器端訪問持久存儲,調(diào)度并執(zhí)行任務(wù),與游戲或虛擬世界的客戶端進(jìn)行通信。
? ? ? ? 用一組相互聯(lián)系的服務(wù)來構(gòu)建這個系統(tǒng),顯然是開始了“分而治之”的過程,分而治之是設(shè)計所有大型計算機(jī)系統(tǒng)的基本方法。每種服務(wù)都可以用一個接口來描述,這讓使用該服務(wù)的程序不會受到底層實(shí)現(xiàn)變更的影響,同時也支持這些實(shí)現(xiàn)可以獨(dú)立地完成。對一個服務(wù)的實(shí)現(xiàn)進(jìn)行變更不應(yīng)該影響到另一個服務(wù)的實(shí)現(xiàn),即使其他的服務(wù)會利用到這個變更的服務(wù)(假定接口和接口的語義沒有變更)。
? ? ? ? 我們采用服務(wù)分解的方法還有其他的原因。從一開始,Darkstar項目就設(shè)計成一個開放源代碼的項目,希望我們能夠放大核心團(tuán)隊的工作,支持其他社區(qū)成員創(chuàng)建更多的服務(wù),豐富核心的功能。維護(hù)一個開源社區(qū)在任何情況下都是復(fù)雜的,我們相信在組成架構(gòu)的
服務(wù)之間擁有最大程度的隔離,將支持在不同服務(wù)實(shí)現(xiàn)層次之間的更高級的隔離。此外,當(dāng)時并不清楚是否存在單一一組服務(wù)能夠適合所有的MMO和虛擬世界。將基礎(chǔ)設(shè)施設(shè)計為一組獨(dú)立的服務(wù),使得這些服務(wù)的不同組合可以在不同的情況下使用,這由使用該基礎(chǔ)設(shè)施的具體項目的需求來決定。Darkstar棧中具體包含哪些服務(wù)可以由一個配置文件來設(shè)置。
3.3.1 宏觀結(jié)構(gòu)
? ? ? ? 圖3-1展示了基于Darkstar項目基礎(chǔ)設(shè)施的游戲或虛擬世界的基本結(jié)構(gòu)。一些服務(wù)器構(gòu)成了游戲或虛擬世界的后端。每個服務(wù)器運(yùn)行著一組選定服務(wù)的副本(稱為Darkstar棧)和游戲邏輯的副本。客戶端將連接到其中一個服務(wù)器,與服務(wù)器保存的該世界的抽象表示進(jìn)行交互。
? ? ? ? 與大多數(shù)的復(fù)制策略不同,游戲邏輯的不同副本不需要處理相同的事件。每個副本可以獨(dú)立地與客戶端進(jìn)行交互。在這個設(shè)計中,復(fù)制主要用于支持伸縮性,而不是確保容錯(雖然我們后面會看到,容錯也實(shí)現(xiàn)了)。而且,游戲邏輯本身不知道、也不需要知道在
其他機(jī)器上運(yùn)行著服務(wù)器的其他副本。游戲程序員編寫的代碼就像在一臺機(jī)器上執(zhí)行一樣,不同副本之間的協(xié)作由Darkstar項目的基礎(chǔ)設(shè)施來完成。實(shí)際上,如果游戲的容量只需要一臺服務(wù)器,基于Darkstar的游戲就能夠在一臺服務(wù)器上運(yùn)行。
? ? ? ? 客戶端連接到游戲邏輯使用的通信機(jī)制是基礎(chǔ)設(shè)施的一部分。這些機(jī)制支持客戶端到服務(wù)器的直接通信,也支持一種“發(fā)布-訂閱”通道,任何發(fā)往通道的消息都會送達(dá)該通道的所有訂閱者。
? ? ? ? ?Darkstar棧由一組元服務(wù)來協(xié)調(diào),這是一組網(wǎng)絡(luò)訪問服務(wù),游戲或虛擬世界的程序員是不可見的。這些元服務(wù)支持棧的各個副本之間進(jìn)行協(xié)作,共同運(yùn)營整個游戲。例如,這些元服務(wù)將所有獨(dú)立的副本持續(xù)工作,如果某個副本失效,就會發(fā)起失效恢復(fù)。這些元服務(wù)還會跟蹤各副本的負(fù)載,在需要的時候重新分配負(fù)載,或者隨時添加新的服務(wù)器,增加總體容量。由于這些服務(wù)對于Darkstar項目的用戶來說是完全隱藏的,所以它們可以隨時改變或移除,或者添加新的服務(wù),這都不需要修改游戲或虛擬世界的代碼。
? ? ? ? ?對于在Darkstar項目環(huán)境中創(chuàng)建游戲或虛擬世界的程序員來說,可見的架構(gòu)就是棧中包含的一組服務(wù)。服務(wù)的全集是可以改變和配置的,但4個基本服務(wù)必須存在,它們構(gòu)成
了運(yùn)營環(huán)境的核心,如圖3-2所示。
3.3.2 基本服務(wù)
? ? ? ? 在這些棧層面的服務(wù)中,最基本的服務(wù)就是“數(shù)據(jù)服務(wù)”(Data Service),游戲或虛擬世界用它來保存、讀取和操作所有持久數(shù)據(jù)。這里的持久概念可能比其他系統(tǒng)中的持久概念更寬泛。對于在Darkstar項目環(huán)境中編寫的游戲或虛擬世界,任何存在時間超過一個任務(wù)的數(shù)據(jù)都被視為持久的,必須在“數(shù)據(jù)服務(wù)”中保存。我們曾假定在這種編程模型中任務(wù)的時間是短暫的(這也是需求),所以幾乎所有用于表示游戲或虛擬世界的服務(wù)器端的數(shù)據(jù)都需要持久。“數(shù)據(jù)服務(wù)”也將運(yùn)行在不同服務(wù)器上的游戲或虛擬世界的副本聯(lián)系在一起,因為所有這些副本都共享同一個(概念上的)“數(shù)據(jù)服務(wù)”實(shí)例。所有的副本都會訪問相同的數(shù)據(jù),所有的副本都可以根據(jù)需要讀取或改變存儲在“數(shù)據(jù)服務(wù)”中的數(shù)據(jù)。
? ? ? ? ?雖然“數(shù)據(jù)服務(wù)”看起來像是使用一個數(shù)據(jù)庫的好地方,但是存儲的需求實(shí)際上與通常條件下對標(biāo)準(zhǔn)數(shù)據(jù)庫的需求有著很大的差別。存儲的對象之間靜態(tài)的關(guān)系很少,游戲中也不需要對存儲的內(nèi)容進(jìn)行復(fù)雜的查詢。相反,簡單的命名策略就足夠了,包括在編程語言層面上對對象的引用。“數(shù)據(jù)服務(wù)”也必須針對延遲進(jìn)行優(yōu)化,而不是針對吞吐量來優(yōu)化。特定服務(wù)要訪問的對象個數(shù)可能很少(我們初步的測算基于一些游戲和虛擬世界的原型,這些測算表明每個任務(wù)大約訪問一打?qū)ο?#xff09;,在這些訪問的對象中,大約一半會在任務(wù)執(zhí)行中改變。
? ? ? ? ?第二個棧層面的服務(wù)是“任務(wù)服務(wù)”(Task Service),它用于調(diào)度或執(zhí)行任務(wù)。這些任務(wù)要么是響應(yīng)從客戶端收到的某個事件,要么是由游戲或虛擬世界服務(wù)器本身的內(nèi)部邏輯發(fā)起的。絕大部分任務(wù)是一次性事件,是由于客戶端的某種動作產(chǎn)生的,它們從“數(shù)據(jù)服務(wù)”中讀取一些數(shù)據(jù),操作這些數(shù)據(jù),可能還進(jìn)行一些通信,然后結(jié)束。任務(wù)也可能生成其他的任務(wù),或者生成定期任務(wù),在特定的時間執(zhí)行或以特定的時間間隔執(zhí)行。所有任務(wù)的執(zhí)行時間必須很短,執(zhí)行一項任務(wù)的最大時間是一個可配置的值,但默認(rèn)值是100毫秒。
? ? ? ? 游戲或虛擬世界的程序員會看到因事件或服務(wù)器邏輯本身而生成的單個任務(wù),但在底層,Darkstar的基礎(chǔ)設(shè)施正盡其所能調(diào)度最多的任務(wù)。特別地,由服務(wù)器邏輯生成的任務(wù)與響應(yīng)客戶發(fā)起的事件而生成的任務(wù)是并行執(zhí)行的,就像響應(yīng)不同客戶端而生成的任務(wù)一樣。這樣的并發(fā)執(zhí)行可能導(dǎo)致數(shù)據(jù)競爭。要處理這種競爭,就需要“任務(wù)服務(wù)”和“數(shù)據(jù)服務(wù)”協(xié)作。在底層,在服務(wù)器程序員不可見的地方,“任務(wù)服務(wù)”調(diào)度的每個任務(wù)都包裝在一個事務(wù)中。這個事務(wù)確保了任務(wù)中的所有操作要么全部完成,要么都不完成。此外,所有改變“數(shù)據(jù)服務(wù)”中對象的值的操作都由該服務(wù)作為中介。如果有多個任務(wù)試圖改變相同的數(shù)據(jù)對象,只有一個任務(wù)會執(zhí)行,其他任務(wù)都會中止,并安排在稍后執(zhí)行。執(zhí)行的那個任務(wù)會運(yùn)行到結(jié)束。當(dāng)執(zhí)行的任務(wù)結(jié)束時,其他的任務(wù)就可以執(zhí)行了。雖然服務(wù)器程序員可以說明訪問的數(shù)據(jù)將被修改,但這不是必需的。如果數(shù)據(jù)對象先被讀取,然后被修改,“數(shù)據(jù)服務(wù)”會在任務(wù)提交之前檢測到這種修改。在讀取時就說明打算進(jìn)行修改,這是一種優(yōu)化,能夠更早地檢測到?jīng)_突,但是不事先說明修改的意圖也不會影響程序的正確性。
? ? ? ? ?將任務(wù)包裝到一個事務(wù)中意味著通信機(jī)制也必須支持事務(wù),只有當(dāng)包裝了消息發(fā)送任務(wù)的事務(wù)提交時,消息才會發(fā)出。這是通過Darkstar棧中余下兩項核心服務(wù)來完成的。
3.3.3 通信服務(wù)
第一個服務(wù)是“會話服務(wù)”(Session Service),它是客戶端和游戲或虛擬世界服務(wù)器之
間通信的中介。在登錄和認(rèn)證后,客戶端與服務(wù)器之間就會建立起一個會話。服務(wù)器通
過會話監(jiān)聽客戶端發(fā)出的消息,解析消息的內(nèi)容,確定生成怎樣的任務(wù)來響應(yīng)該消息。
客戶端通過會話接收來自服務(wù)器的響應(yīng)。這些會話隱藏了客戶端和服務(wù)器的真實(shí)端點(diǎn),
這一點(diǎn)對于Darkstar的多機(jī)伸縮性策略是很重要的。會話也負(fù)責(zé)確保維持消息的順序。
如果來自某個客戶端的前一條消息所引發(fā)的任務(wù)還沒有完成,后一條消息就不會提交。
在“會話服務(wù)”對任務(wù)進(jìn)行這樣的排序之后,“任務(wù)服務(wù)”就得到了極大的簡化。“任務(wù)
服務(wù)”可以假定它在任何時候收到的任務(wù)在本質(zhì)上都是并發(fā)的。對來自特定客戶端的消
息排序是Darkstar框架中唯一的消息排序保證機(jī)制,外部觀察者看到的多個客戶端之間
的消息順序,與游戲或虛擬世界內(nèi)看到的順序有很大不同。
3.3.3 通信服務(wù)
? ? ? ? ?第一個服務(wù)是“會話服務(wù)”(Session Service),它是客戶端和游戲或虛擬世界服務(wù)器之間通信的中介。在登錄和認(rèn)證后,客戶端與服務(wù)器之間就會建立起一個會話。服務(wù)器通過會話監(jiān)聽客戶端發(fā)出的消息,解析消息的內(nèi)容,確定生成怎樣的任務(wù)來響應(yīng)該消息。客戶端通過會話接收來自服務(wù)器的響應(yīng)。這些會話隱藏了客戶端和服務(wù)器的真實(shí)端點(diǎn),這一點(diǎn)對于Darkstar的多機(jī)伸縮性策略是很重要的。會話也負(fù)責(zé)確保維持消息的順序。如果來自某個客戶端的前一條消息所引發(fā)的任務(wù)還沒有完成,后一條消息就不會提交。在“會話服務(wù)”對任務(wù)進(jìn)行這樣的排序之后,“任務(wù)服務(wù)”就得到了極大的簡化。“任務(wù)服務(wù)”可以假定它在任何時候收到的任務(wù)在本質(zhì)上都是并發(fā)的。對來自特定客戶端的消息排序是Darkstar框架中唯一的消息排序保證機(jī)制,外部觀察者看到的多個客戶端之間的消息順序,與游戲或虛擬世界內(nèi)看到的順序有很大不同。
? ? ? ? ?會話和通道的復(fù)雜性有多種原因,其中之一就是它們必須遵守任務(wù)的事務(wù)語義。因此,會話連接或通道上的實(shí)際消息傳送不能夠在調(diào)用相應(yīng)的send()方法時發(fā)生,它只能夠在該方法所處的任務(wù)提交時才能發(fā)生。這些通信機(jī)制為我們實(shí)現(xiàn)伸縮性機(jī)制的第二部分奠定了基礎(chǔ)。既然所有通信都必須通過Darkstar會話或通道的抽象層,而這些抽象層又不暴露客戶端或服務(wù)器通信的真實(shí)端點(diǎn),那么在實(shí)體通信和通信起止端的實(shí)際位置之間就存在著一個抽象層。這意味著我們可以在Darkstar系統(tǒng)中將服務(wù)器通信的端點(diǎn)從一臺機(jī)器移到另一臺機(jī)器,同時不會改變客戶端對這次通信的感覺。從游戲或虛擬世界的視角來看,通信也是經(jīng)過一個會話或通道。但是底層的基礎(chǔ)設(shè)施可以隨著時間的推移和負(fù)載的變化,根據(jù)負(fù)載平衡的需要,將會話或通道從一臺機(jī)器移到另一臺機(jī)器。
3.3.4 任務(wù)的可移動性
? ? ? ? ?要實(shí)現(xiàn)負(fù)載均衡的能力,其關(guān)鍵之處在于,對于我們要求的編程模型和必須使用的基本棧服務(wù),響應(yīng)客戶端事件或游戲內(nèi)部事件的任務(wù)可以從任何一臺運(yùn)行著Darkstar棧和游戲或虛擬世界副本的機(jī)器上移動到另一臺同樣的機(jī)器上。任務(wù)本身是用Java編寫的(注2),這意味著只要(物理)機(jī)器的運(yùn)行時棧中包含相同的Java虛擬機(jī),任務(wù)就能夠運(yùn)行。任務(wù)讀取和操作的所有數(shù)據(jù)必須從“數(shù)據(jù)服務(wù)”獲得,“數(shù)據(jù)服務(wù)”是所有機(jī)器上的游戲或虛擬世界的實(shí)例和Darkstar棧所共享的。通信由“會話服務(wù)”或“通道”來實(shí)現(xiàn)中介,它們抽象了通信的真實(shí)端點(diǎn),而且支持特定的會話和通道從一個服務(wù)器移動到另一個服務(wù)器上。因此,所有任務(wù)都可以運(yùn)行在任意一個游戲服務(wù)器的實(shí)例上,同時不改變?nèi)蝿?wù)的語義。
? ? ? ?這使得Darkstar的基本伸縮機(jī)制看起來很簡單。如果有一臺機(jī)器超載了,只要將一些任務(wù)從這臺機(jī)器移到另一臺負(fù)載較小的機(jī)器就行了。如果所有的機(jī)器都超載了,就向運(yùn)行著Darkstar棧和游戲/虛擬世界的集群中添加新的機(jī)器。底層的負(fù)載平衡軟件會將負(fù)載分發(fā)給新的機(jī)器。
? ? ? ? 對單臺機(jī)器的負(fù)載進(jìn)行監(jiān)控并在需要時重新分配負(fù)載,這是元服務(wù)的工作。這些元服務(wù)是網(wǎng)絡(luò)層面的服務(wù),對于游戲或虛擬世界的程序員是不可見的,但是它們對Darkstar棧中的服務(wù)是相互可見的。例如,這些元服務(wù)會監(jiān)控哪些機(jī)器正在運(yùn)行(并監(jiān)控是否有機(jī)器失效),哪些用戶與某臺機(jī)器有關(guān),不同的機(jī)器當(dāng)前的負(fù)載。由于元服務(wù)對于游戲或虛擬世界的程序員是不可見的,所以它們在任何時候都可以改變,不會影響到游戲邏輯的正確性。這讓我們能夠嘗試不同的策略和方法,實(shí)現(xiàn)系統(tǒng)的動態(tài)負(fù)載平衡,也讓我們能夠豐富基礎(chǔ)設(shè)施所需的元服務(wù)集合。
? ? ? ? ?同樣,我們使用實(shí)現(xiàn)多機(jī)伸縮機(jī)制來實(shí)現(xiàn)系統(tǒng)的高容錯。由于任務(wù)和通信機(jī)制所使用的數(shù)據(jù)是與具體機(jī)器無關(guān)的,所以很明顯,我們可以將任務(wù)從一臺機(jī)器移到另一臺機(jī)器上。但是如果機(jī)器失效,我們?nèi)绾位謴?fù)在那臺機(jī)器上執(zhí)行的任務(wù)呢?答案很簡單:任務(wù)本身
也是持久對象,保存在系統(tǒng)的“數(shù)據(jù)服務(wù)”中。因此,如果一臺機(jī)器失效,該機(jī)器上正在執(zhí)行的所有任務(wù)都被視為中斷的事務(wù),會重新調(diào)度在不同的機(jī)器上執(zhí)行。盡管這種重新調(diào)度比在一臺機(jī)器上重新調(diào)度中斷的任務(wù)的延遲要長,但系統(tǒng)的正確性是不變的。系統(tǒng)的用戶(游戲玩家或虛擬世界的居民)頂多會注意到響應(yīng)時間暫時有點(diǎn)延長。這樣的延遲讓人有點(diǎn)不舒服,但總好過現(xiàn)在其他游戲或虛擬世界環(huán)境中服務(wù)器崩潰所造成的影響。在那些環(huán)境中,會導(dǎo)致玩家掉線,還可能導(dǎo)致相當(dāng)一部分游戲狀態(tài)的丟失。
3.4 關(guān)于架構(gòu)的思考
? ? ? ? 也許所有人關(guān)于架構(gòu)及其實(shí)現(xiàn)的第一個問題就是它的性能。雖然未經(jīng)深思熟慮就對架構(gòu)進(jìn)行優(yōu)化是諸多罪惡之源,但是我們也可能設(shè)計出一個架構(gòu),而它的實(shí)現(xiàn)根本不可能達(dá)到好的性能。由于Darkstar架構(gòu)的一項基本選擇,這種擔(dān)心是真實(shí)的。而且由于游戲行業(yè)的特點(diǎn),確定服務(wù)器基礎(chǔ)設(shè)施的性能是很難的。
? ? ? ? 要確定游戲或虛擬世界服務(wù)器基礎(chǔ)設(shè)施的性能,其難度源自一個簡單的事實(shí):沒有針對大規(guī)模MMO或虛擬世界的性能測試標(biāo)準(zhǔn)或共同接受的例子。缺少性能測試標(biāo)準(zhǔn)并不奇怪,因為絕大多數(shù)游戲或虛擬世界的服務(wù)器組件都是針對特定的游戲或虛擬世界從頭開發(fā)的。只有少數(shù)的通用基礎(chǔ)設(shè)施可以作為可復(fù)用的構(gòu)建塊,這些組件一般是事后從特定的游戲或虛擬世界中提取出來的,提供給其他構(gòu)建類似游戲的人使用。也許是因為游戲行業(yè)還比較年輕,或是因為娛樂業(yè)中出現(xiàn)重要技術(shù)的偶然性,結(jié)果是沒有共同接受的性能測試標(biāo)準(zhǔn)用于測試新的基礎(chǔ)設(shè)施,也無法對不同的基礎(chǔ)設(shè)施進(jìn)行比較。
? ? ? ? ?關(guān)于游戲或虛擬世界的預(yù)期計算、數(shù)據(jù)操作和通信負(fù)載也基本上沒有什么資料,所以很難創(chuàng)建性能測試標(biāo)準(zhǔn)程序。部分原因是已有的服務(wù)器都是定制的。每臺服務(wù)器都是為特定的游戲或虛擬世界設(shè)計的,所以考慮的是那款游戲或虛擬世界的具體負(fù)載特征。而且,這種狀況也是因為游戲業(yè)的強(qiáng)烈的保密性。在游戲業(yè)中,關(guān)于一款游戲開發(fā)的信息是嚴(yán)格保密的,而且發(fā)布游戲的實(shí)現(xiàn)方式也是嚴(yán)格保密的。同時,行業(yè)中的許多人對這些信息是不感興趣的。大量的思考和討論集中在藝術(shù)設(shè)計、故事情節(jié)或玩家交互模式上,這
些令新游戲更有趣、更好玩,而不是游戲服務(wù)器的設(shè)計方式和游戲為支持并發(fā)玩家(這個數(shù)字也是嚴(yán)格保密的)所采取的伸縮性技術(shù)。所以,獲得現(xiàn)有的游戲和虛擬世界的這種服務(wù)器負(fù)載信息都很困難。
? ? ? ? 根據(jù)我們的經(jīng)驗,即使我們能夠找來開發(fā)者,談?wù)撍麄兊挠螒蚧蛱摂M世界加在服務(wù)器上的負(fù)載,他們也常常會報告錯誤的信息。這不是因為他們想保持商業(yè)優(yōu)勢而故意錯誤報告他們服務(wù)器的情況,而是因為他們真的自己不也了解。在游戲服務(wù)器上基本不會加入一些手段,讓他們收集有關(guān)服務(wù)器真實(shí)性能或完成事務(wù)的信息。對于這種服務(wù)器的分析一般最多是經(jīng)驗性的。程序員在服務(wù)器上工作,直到它讓游戲玩起來有趣,這是一種迭代式的工作方式,而不是仔細(xì)對代碼本身進(jìn)行測量。在這些系統(tǒng)中,更多的是手工技術(shù)活,而不是科學(xué)測定。
? ? ? ? 這并不是說,這些游戲或虛擬世界后面的服務(wù)器是一些粗制濫造的代碼,也不是說它們做得不好。實(shí)際上,許多代碼是效率杰作,展示了聰明的編程技巧,也展示了針對高要求的應(yīng)用構(gòu)造一次性、專門目的服務(wù)器的優(yōu)勢。但是,為每個游戲或虛擬世界構(gòu)建一個新服務(wù)器的習(xí)慣意味著人們不太注意積累構(gòu)建這種服務(wù)器所需的知識,也沒有共同接受的機(jī)制來比較不同的基礎(chǔ)設(shè)施。
3.4.1 并行與延遲
? ? ? ? 缺少有關(guān)服務(wù)器可接受的性能的資料,這一點(diǎn)引起了Darkstar團(tuán)隊的特別關(guān)注,因為我們所做的一些關(guān)鍵決定,都是圍繞著如何能夠從游戲或虛擬世界服務(wù)器中獲得好的性能。也許Darkstar架構(gòu)和一般實(shí)踐之間的最大區(qū)別就在于,Darkstar架構(gòu)拒絕在服務(wù)器的主內(nèi)存中存放任何重要的信息。所有生存周期超過一次具體任務(wù)的數(shù)據(jù)都需要持久在“數(shù)據(jù)服務(wù)”中,這是實(shí)現(xiàn)Darkstar基礎(chǔ)設(shè)施功能的核心。這讓基礎(chǔ)設(shè)施能夠檢測到并發(fā)問題,反過來又讓系統(tǒng)能夠?qū)Τ绦騿T隱藏這些問題,同時讓服務(wù)器能夠利用多核架構(gòu)。它也是實(shí)現(xiàn)整體伸縮性的關(guān)鍵組件,支持任務(wù)從一臺服務(wù)器移動到另一臺服務(wù)器,從而在一組機(jī)器上實(shí)現(xiàn)負(fù)載平衡。
? ? ? ? 在游戲和虛擬世界服務(wù)器領(lǐng)域,任何時候都持久保存游戲狀態(tài)是一種異端邪說,因為人們普遍很關(guān)心延遲。在編寫這種服務(wù)器時,大家的觀點(diǎn)是只有將所有信息都放在內(nèi)存中才能讓延遲足夠小,達(dá)到要求的響應(yīng)時間。可以偶爾保存狀態(tài)的快照,但對交互速度的要求表明,這種長時間的操作只能夠偶爾進(jìn)行,而且要在后臺進(jìn)行。所以,從表面上看,我們的架構(gòu)似乎絕不可能達(dá)到足夠好的性能,從而服務(wù)于它的目標(biāo)應(yīng)用。雖然要求數(shù)據(jù)持久肯定是這個架構(gòu)的主要不同之處,而且要求通過“數(shù)據(jù)服務(wù)”來訪問數(shù)據(jù)會在架構(gòu)中引入一定的延遲,但我們相信我們所采取的方式更具有競爭力,原因有幾點(diǎn)。首先,我們相信能夠讓訪問內(nèi)存數(shù)據(jù)和訪問“數(shù)據(jù)服務(wù)”中的數(shù)據(jù)之間的差異遠(yuǎn)遠(yuǎn)小于一般人們的看法。雖然在概念上每個生命周期超出一次任務(wù)的對象都需要從持久存儲中讀出,并寫入持久存儲,但實(shí)現(xiàn)這種存儲可以利用人們在數(shù)據(jù)庫緩存和一致性方面多年的研究成果,從而減少因這種方式而導(dǎo)致的數(shù)據(jù)訪問延遲。
? ? ? ? 如果我們能夠?qū)⒃L問局限在一個特定服務(wù)器上的幾組特定對象,就更是如此了。如果用到一組特定對象的那些任務(wù)都運(yùn)行在一臺服務(wù)器上,那么就可以利用該服務(wù)器的緩存,達(dá)到接近內(nèi)存的對象讀寫速度(受到需要滿足的持久性約束的影響)。我們可以識別任務(wù)屬于哪些玩家或虛擬世界的哪些用戶。這樣,我們就可以利用基礎(chǔ)設(shè)施中服務(wù)所接收到的數(shù)據(jù)訪問和通信請求,來收集特定時刻游戲或虛擬世界中數(shù)據(jù)訪問模式和通信模式的信息。有了這些信息,我們相信能夠非常準(zhǔn)確地估計哪些玩家應(yīng)該與另一些玩家放在一起。因為我們可以根據(jù)需要將玩家移動到任何服務(wù)器上,所以能夠根據(jù)觀察到的運(yùn)行
? ? ? ? 這聽起來非常像目前在大規(guī)模游戲和虛擬世界中為實(shí)現(xiàn)伸縮性而采用的地理區(qū)域分解技術(shù)。在這種技術(shù)中,服務(wù)器開發(fā)者將世界分解成一些區(qū)域,將它們指派給一些服務(wù)器,不同的區(qū)域就成為用戶分區(qū)的機(jī)制。同一區(qū)域的玩家比不同區(qū)域的玩家進(jìn)行交互的可能性更大,所以這種集中在一個服務(wù)器上的優(yōu)勢就體現(xiàn)出來了。不同之處在于,目前的地理區(qū)域分解是在游戲開發(fā)過程中進(jìn)行的,被編入源代碼,放到服務(wù)器上。而我們的位置集中基于運(yùn)行時的信息,可以根據(jù)游戲中發(fā)生的實(shí)際玩法和交互模式來實(shí)現(xiàn)動態(tài)調(diào)整。這類似于編譯時優(yōu)化和運(yùn)行時優(yōu)化之間的區(qū)別。前一種方法試圖針對程序所有可能的運(yùn)行進(jìn)行優(yōu)化,而后一種方法試圖針對當(dāng)前的運(yùn)行進(jìn)行優(yōu)化。
? ? ? ? 我們不相信我們能夠消除內(nèi)存訪問和持久訪問之間的差別,而且我們也不認(rèn)為有必要這樣做,最后讓這種架構(gòu)比使用內(nèi)存的架構(gòu)性能更好。要知道,通過讓所有的數(shù)據(jù)持久,我們可以支持在服務(wù)器上使用多線程(從而也支持多核)。盡管我們不相信并發(fā)是完美的(即對于每個添加的核,我們都能充分利用),但我們確實(shí)相信在游戲和虛擬世界中可以使用大量的并行運(yùn)算(初步的結(jié)果也證實(shí)了這種看法)。如果可使用的并行運(yùn)算超過我們可能引入的延遲,那么游戲或虛擬世界的總體性能就會更好。
3.4.2 賭未來
? ? ? ? 我們對多核處理器中多線程的信心基本上是在賭處理器將來的發(fā)展方向。目前服務(wù)器的處理器提供2~32個核,我們相信將來的芯片設(shè)計將集中向更多的核發(fā)展,而不是讓現(xiàn)有的核以更高的時鐘頻率運(yùn)行。當(dāng)我們在幾年前開始這個項目時,這種賭博似乎比現(xiàn)在更具投機(jī)性。那時候,我們在做展示時常常說這種設(shè)計是一種“假定”的演練,說我們正嘗試一種架構(gòu),如果芯片性能更好地支持多線程而不是單線程的時鐘速度,這種架構(gòu)將是可行的。這就是在研究實(shí)驗室中進(jìn)行這類項目的好處之一,可以接受設(shè)計方法中存在很高的風(fēng)險,探索一個將來也許在商業(yè)上可行的領(lǐng)域。我們決定構(gòu)建一個以多線程為中心的架構(gòu),與這個決定做出時相比,目前芯片設(shè)計的趨勢讓我們看得更清楚。(注3)即使我們只能得到50%的完美并發(fā),如果我們能把使用持久存儲的延遲控制在使用內(nèi)存的延遲的2~16倍,就能夠在性能上持平。我們相信在并發(fā)方面以及減少訪問持久狀態(tài)和全內(nèi)存方案之間的差異方面都可以做得更好。但是結(jié)果主要取決于構(gòu)建于這個基礎(chǔ)設(shè)施之上的應(yīng)用的使用模式(我們曾提到,這一點(diǎn)很難發(fā)現(xiàn))。
? ? ? ? 我們也不應(yīng)認(rèn)為減少延遲就是這個基礎(chǔ)設(shè)施的唯一目標(biāo)。通過將游戲或虛擬世界服務(wù)器端的對象全部保存在“數(shù)據(jù)服務(wù)”中,我們把因服務(wù)器失效而導(dǎo)致的數(shù)據(jù)丟失減到了最小。實(shí)際上,在大多數(shù)情況下,服務(wù)器失效時用戶只會注意到延時有一點(diǎn)增加,因為任務(wù)(它們本身也是持久對象)從失效的服務(wù)器移到了另一臺服務(wù)器上。沒有數(shù)據(jù)會丟失。
? ? ? ? 一些緩存機(jī)制可能導(dǎo)致丟失幾秒鐘的游戲成果,但即使是這樣,也比在線游戲和虛擬世界目前使用的機(jī)制好得多,它們只是將偶爾進(jìn)行內(nèi)存快照作為主要的持久方式。在它們的基礎(chǔ)設(shè)施中,如果服務(wù)器在不巧的時間崩潰,可能會造成數(shù)小時的游戲成果丟失。只要延遲是可以接受的,Darkstar所使用持久機(jī)制的可靠性更高,這對于在這個基礎(chǔ)設(shè)施上構(gòu)建系統(tǒng)的開發(fā)者和系統(tǒng)的用戶來說都是優(yōu)點(diǎn)。
3.4.3 簡化程序員的工作
? ? ? ? 實(shí)際上,如果在支持伸縮性的同時減少延遲是服務(wù)器開發(fā)者的唯一目標(biāo),那么開發(fā)者最好的方法就是專門針對特定的游戲,編寫自己的分布式和多線程基礎(chǔ)設(shè)施。但這要求服務(wù)器開發(fā)者處理復(fù)雜的分布式和并發(fā)編程。在為速度需求而過度煩惱之前,我們應(yīng)該想到Darkstar的第二個同樣重要的目標(biāo),即在支持多線程、分布式游戲產(chǎn)品的同時,為程序員提供一個單機(jī)單線程的開發(fā)模型。
? ? ? ?在相當(dāng)大的程度上,我們已經(jīng)實(shí)現(xiàn)了這一目標(biāo)。通過將所有任務(wù)封裝到事務(wù)中,并在“數(shù)據(jù)服務(wù)”中檢測數(shù)據(jù)沖突,程序員就能夠享受到多線程的好處,又不必在他們的代碼中引入鎖協(xié)議、同步和信號量。程序員不必?fù)?dān)心如何將玩家從一臺服務(wù)器移到另一臺服務(wù)器,因為Darkstar為他們提供了透明的負(fù)載平衡。編程模型雖然有自己的風(fēng)格和限制,但社區(qū)中的早期成員認(rèn)為,這對他們開發(fā)的那種游戲和虛擬世界來說是比較自然的。不幸的是,我們發(fā)現(xiàn)我們不能夠向程序員隱藏所有的東西。當(dāng)在Darkstar上編寫的第一個游戲表現(xiàn)出極少的并行度(以及意料之外的糟糕性能)時,這一點(diǎn)就明確了。通過檢查源代碼,我們很快就發(fā)現(xiàn)了原因。游戲中的數(shù)據(jù)結(jié)構(gòu)設(shè)計導(dǎo)致了游戲中所有的狀態(tài)改變都只涉及一個對象,并由它來協(xié)調(diào)所有的工作。使用這個對象實(shí)際上使得游戲中所有動作序列化執(zhí)行,這使得基礎(chǔ)設(shè)施不能夠發(fā)現(xiàn)并利用并發(fā)計算。
? ? ? ?當(dāng)我們發(fā)現(xiàn)這一點(diǎn)時,我們與游戲開發(fā)者進(jìn)行了長時間的討論,主題是在設(shè)計對象時需要考慮到并發(fā)訪問。通過對游戲中數(shù)據(jù)對象進(jìn)行審查,我們發(fā)現(xiàn)了一些類似的情況:數(shù)據(jù)設(shè)計方案排除了并發(fā)的可能性(并非出自設(shè)計者本意)。當(dāng)這些對象重新設(shè)計之后,系統(tǒng)的整體性能增加了好幾個數(shù)量級。
? ? ? ? 這告訴我們,不可能讓使用Darkstar的開發(fā)者完全不知道系統(tǒng)底層的并發(fā)和分布式實(shí)質(zhì)。但是,他們對系統(tǒng)這方面特點(diǎn)的知識不需要包括并發(fā)控制、鎖,以及在系統(tǒng)的各個分布式部分之間的通信。實(shí)際上,他們只需要在設(shè)計活動中確保他們的數(shù)據(jù)對象定義能夠充
分利用并發(fā)。這種設(shè)計一般只需要確保對象定義是自包含的,它們的操作不需要依賴其他對象的屬性。這一點(diǎn)對于任何系統(tǒng)來說,都不是不好的設(shè)計原則
? ? ? ?關(guān)于Darkstar架構(gòu),我們還有許多方面沒有測試,或者說我們并未完全理解。雖然我們已經(jīng)得到了一個系統(tǒng),使得多臺機(jī)器能夠利用多線程運(yùn)行一個游戲或虛擬世界,同時對服務(wù)器程序員(幾乎)保持透明,但是我們還沒有通過添加核心服務(wù)之外的其他服務(wù),來檢驗該架構(gòu)的能力。由于Darkstar任務(wù)的事務(wù)本質(zhì),這可能比我們開始設(shè)想的要復(fù)雜得多,但我們希望這些添加的服務(wù)不需要參與到核心服務(wù)的事務(wù)中。我們已經(jīng)開始試驗通過不同的方式來收集系統(tǒng)負(fù)載的信息和實(shí)現(xiàn)負(fù)載平衡。幸運(yùn)的是,因為實(shí)現(xiàn)這種負(fù)載平衡的機(jī)制對于使用系統(tǒng)的程序員是完全不可見的,所以我們可以移除老的方式,引入新的方式,同時又不影響Darkstar的用戶。
? ? ? ? 作為一個架構(gòu),Darkstar展示了一些創(chuàng)新的方法,這使它變得很有趣。它試圖構(gòu)造一個游戲或虛擬世界的基礎(chǔ)設(shè)施,使其具有企業(yè)級軟件一樣的可靠性,同時又滿足游戲行業(yè)對延遲、通信和伸縮性的要求。它是目前為數(shù)不多的這類嘗試之一。通過利用更多機(jī)器和更多線程來實(shí)現(xiàn)效率,我們希望能夠抵消因使用持久存儲機(jī)制而導(dǎo)致的延遲增加。最后,游戲和虛擬世界環(huán)境中極為不同的情況,即客戶端的處理很多而服務(wù)器端的處理很少,與我們常見的高并發(fā)、分布式系統(tǒng)環(huán)境形成了鮮明的對比。現(xiàn)在說這個架構(gòu)是否成功還為時尚早,但我們相信它已經(jīng)很有趣了。
總結(jié)
以上是生活随笔為你收集整理的架构师必看-架构之美第15章伸缩性架构设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何阻止程序联网
- 下一篇: 身份证号码校验(JavaScript)