這是一個叫OAR-01的《我的世界》公益服務器,從今年6月份開始運行,至今已經3個月了。主要玩法為生存和粘液科技,在暑假“高峰期”曾有過20人(其實不是什麼高峰)同時在線的情況。
玩家創作的牛牛水道,來自七星博士
由於是公益服,主要資金來源是玩家(也是群友)的捐贈,以及自己用愛發電。所以維護一個性能卓越、成本低廉並且還有較強可玩性的服務器是我的主要目標。當然了,在這一切實現之前,還有一個更大的目標,就是使用雲原生進行遊戲和相關服務的部署。
雲原生是指所有的互聯網服務都是在雲服務器上部署的,不涉及本地機房或IDC機房託管之類。雲原生有很多好處,具體的優勢挖個坑,等會兒細說。
選擇一個服務端
首先是服務端的選擇。服務端主流有原版、插件和模組三種。原版就是官方推出的Vallina版本的核心。原版沒有對性能優化,同時也有很多的bug/特性,這肯定是不能用的。
模組服是Forge架構作為核心,並且添加大量模組以供遊玩的服務器。這類服務器好處在於遊戲內容多樣,玩家能夠體驗更多的不同於原版的遊戲內容。但問題也很大,一方面,一些熱門的模組大多數玩家都玩過,沒有新鮮度,另一方面,冷門的模組往往學習成本高昂,玩家玩了也不知道怎麼玩。同時,模組服還需要高主頻的處理器,這一點在成本有限的雲原生部署中很難做到。
那麼我的目光就轉向了插件服。插件服中最具代表性的是一款叫PaperMC的開源服務端。其修復了大多數的官方bug和不合理特性,還提供了大量的性能優化和客製化選項。
選擇硬件
選擇完軟件就要選擇硬件了。由於本人最早接觸公有云是騰訊雲,域名註冊也是在騰訊雲,所以本文中用到的公有云服務提供商均為騰訊雲。其實其他雲廠商的服務也是一樣的,只不過可能價格、優惠力度會有不同。
在遊戲服務器的選擇上,我最終選擇了騰訊雲的SA2競價實例(Cloud Vitrual Machine, CVM),使用AMD霄龍Rome架構,性能不錯,並且價格方面比Intel的至強系列便宜不少。同時,競價實例價格是按量計費價格基礎上的2折,不可謂不便宜。
有些小夥伴可能會問,競價實例難道不會發生回收事件嗎?首先,只買一臺競價實例,被回收的概率的基數就小;其次,只要做好了核心業務的分離,做好硬盤鏡像,可以在短時間內切換回按量計費,並且沒有數據的丟失;最後,競價實例的2折優惠價是任何其他服務無法比擬的,這個風險值得冒險。同時,我自己的服務器已經連續運行了3個月,暫時還沒有發生過回收的情況。
更新四題圖,故事的開始
網絡的選擇和優化
在帶寬方面,原來我使用的是按量計費,一個G需要0.8元。與按量計費相對的是按帶寬包月計費,帶寬計費也不便宜,或者說對於小規模業務來說很貴,尤其是對於5Mbps以上的帶寬,甚至要100元每Mbps,這就意味著如果同時在線人數較多,那必然會增加帶寬峰值,峰值越高費用上升的速度越高。所以我只能選擇按量計費,雖然一個G需要0.8元,但好處是沒有帶寬的限制,速度要多快有多快,比較適合業務初創期對流量還不確定的情況。
做了一個簡單的計算,對於《我的世界》,每天的最高同時在線人數乘以30,即是一個月所需要的帶寬費用。而隨著玩家的不斷增多,流量成本飛漲。終於在今年(2021年)的8月的某一天,我陷入了焦慮……原因是玩家飛快增長,原本預計一個月流量費用在100左右,突然變成了預計一個月流量費用需要1000+。這也是我遇到的第一個困難。
是困難就需要克服,克服困難的唯一辦法就是創新。經過一整晚的深思熟慮,在對騰訊雲產品的反覆斟酌之後,我找到了解決出路——使用輕量應用服務器的廉價帶寬,搭建應用層代理。
騰訊雲最近主推一款輕量應用服務器(lighthouse, LH),其價格一般很便宜,但配置也比較死板不能調整。其中,網絡方面最具有性價比的LH是一款5Mbps帶寬、每月50元的實例,換算下來每Mbps帶寬只需要10元,而擁有更高帶寬的LH實例,單位帶寬的價格都比這貴得多。同時,由於友商的不斷競爭,LH還有很多優惠,最便宜的可以到3元每Mbps每月。這價格已經遠遠比大多數的託管便宜了,更何況這帶寬資源還是網絡中的王者——BGP線路。
BGP線路是國內最優質的公網帶寬資源,對所有網絡環境不分移動電信,均有最低的延遲。問題就出在如何利用將遊戲核心的接入點遷移到性價比更高的LH上。顯然不能直接把遊戲拷貝過去,因為便宜的LH配置都比較低,前文也提到,競價實例是性價比最高的計算資源。也不能簡單買一臺LH就完事,因為帶寬顯然比5Mbps要高得多,肯定要買很多個LH實例,然後各個實例負責接入一部分的玩家。一方面多個IP是個問題,玩家需要自行選擇某個人數比較少的LH接入遊戲,這並不優雅,也沒有操作性;另一方面,簡單地轉發流量也不可行,因為遊戲核心會認為所有的玩家都是從某個內網的LH實例地址加入遊戲,無法獲取源客戶端的IP信息,這樣就無法實現基於IP的任何操作:比如將不良口碑的玩家封禁,比如限制每個IP的登陸數量,以及地圖的一些功能。
下面是我的對於網絡問題的解決方案:
一方面,使用BungeeCord或Velocity等應用進行遊戲應用層的反向代理。這兩款軟件都是轉為Minecraft開發的第七層代理程序,可以直接讀取遊戲數據包內的IP地址信息,並且添加轉發信息之後轉發到指定地址;另一方面,使用域名解析(Domain Name System, DNS)作為負載均衡(Load Blance, LB),DNS智能地將將一個域名隨機解析為多個LH接入點中的某一個IP地址,這樣玩家理論上會隨即進入一個實例,而不用記錄複雜繁瑣的IP地址信息。這裡要注意的細節是需要購買一款TTL較低的套餐,以防止過長的緩存導致大量玩家擠入一個接入點。
以上解決方案都是依託雲原生的部署才能實現,LH接入點是公有云才有的獨家的服務,而DNS負載均衡也是依託公有云的DNS解析才實現的,繼續閱讀您將看到更多的關於雲原生的部署在成本和性能體驗上的優勢利好。
更新五題圖,故事的結局和真實的世界
超大規模地圖
解決了帶寬問題遊戲就正常運行了。為了更好的體驗,我給我的世界加入了網頁地圖插件(dynmap)。網頁地圖插件讀取地圖文件,並且進行渲染,將渲染好的地圖“瓦片(tiles)”存儲到文件系統或數據庫中。
一開始我是使用數據庫來存儲的。因為對於海量數據,數據庫的訪問響應速度比文件存儲高的多。但是數據庫並不是用來存儲圖片的,因為這會佔用大量的硬盤空間,導致主從備份由於開銷太大難以進行,同時MySQL使用的innoDB引擎在刪除記錄時是“虛刪除”,只是將被刪除的記錄標記為被刪除,並不會真正的刪除,等到下次有數據要寫入的時候才會寫入,這雖然加速了刪除速度,但也導致了磁盤空間的浪費——尤其是在存儲大量圖片的時候,人們將這種碎片空間叫做“數據空洞”。
為了整理碎片空間,需要執行“重構數據表”的操作,而這一操作更是我的噩夢——需要和當前已使用容量一樣大的存儲空間進行暫存。總的來說數據庫在存儲地圖瓦片時會大量的浪費磁盤資源,並且刪改不靈活。雲硬盤價格還是比較貴的,先前的方案需要硬盤200G的空間給網頁地圖,在618的優惠並且按一整年購買優惠之後,價格在每月40元,並且這些數據還需要快照備份,快照每月20元,還是挺貴的。
網頁地圖,https://oar-01.ruofengx.cn/map/#world;surface;124,64,-998;4
解決問題首先要認識問題。地圖“瓦片”的讀寫有個特點,就是寫入速度不需要多少,而讀取時需要大量併發加載,因為渲染地圖往往很慢,而玩家在瀏覽器中打開地圖往往一秒就是幾百個請求。如果使用文件系統,不使用數據庫,前面的問題雖然是沒有了,但導致系統資源因為大量的IO而被掛起,系統最終會失去響應。數據庫的初衷就是解決這一類問題的,但是由於成本受限,這裡我不想用數據庫進行存儲。
這次解決問題的靈感來自於我的網盤項目:網盤設計初衷就是利用對象存儲(Cloud Object Store, COS)以達成無限存儲的目的。而對像存儲可以應對大量的讀請求。但是在我要說的案例中,地圖渲染會大量的讀寫工作目錄,對象存儲又不適合直接用做寫入介質,因為每一個更改都會產生一個請求,對象存儲有一個計費項目就是請求數量,大量的讀寫導致讀寫請求費用飆升。
於是,我又將目光轉向了混合存儲:使用按每小時存儲量計費的文件存儲(Cloud File System, CFS)作為地圖渲染的工作目錄,使用cos_migrate_tool定期將渲染好的地圖“瓦片”上傳至對象存儲中,再給對象存儲單獨配置內容分發網絡(Content Delivery Network, CDN),訪問者在請求地圖“瓦片”時會被最外層的CDN重定向到瓦片對象存儲的CDN域名中,然後瓦片資源的CDN根據單獨配置的規則返回對應資源。
這樣有三個好處,一是費用便宜。CFS在沒有優惠的情況下每100GB每月35元,但這是每小時按量計費的,如果這個月平均只用了10G那就只要3.5元,非常靈活;而對象存儲則更加便宜,標準存儲100GB一個月只需要8元,而在地圖渲染期間內的瓦片上傳(每小時40000“瓦片”生成)是一次性的,徹底完成後只會有少許的文件更新(每小時約2000個“瓦片”更新)上傳,對象存儲的請求費用也是可控的。以上方案通過充分利用雲原生帶來的產品紅利,徹底解決了使用數據庫存儲中出現的問題。同理,使用CFS存儲世界存檔也是一樣的。
以上就是從2021年6月到9月OAR-01世界運維的主要內容。
網頁地圖的鏈接:點擊跳轉
如果你也想來體驗原版生存,可以看這個網頁,這裡面有一鍵開始遊戲的方法。