王者榮耀為什么不使用微服務(wù)架構(gòu)?



微服務(wù)為了把業(yè)務(wù)完美拆解,把原來的同一個進程里的模塊拆分成不同的服務(wù),顯著增加額外的網(wǎng)絡(luò)開銷。更別說什么Service Mesh,各種Gateway,Proxy,Sidecar簡直就是擔(dān)心延遲太低。
微服務(wù)基本只有request/response的模式。做不了streaming?微服務(wù)通常要求應(yīng)用是無狀態(tài)的才能做到水平擴展。streaming本身就是加入了狀態(tài)。
我可以想像,為了提高通訊的性能,一場英雄聯(lián)盟游戲很可能會使用同一個服務(wù)器負責(zé)這10個玩家之間的通訊,這樣就使得數(shù)據(jù)可以在本地交換,性能最大化。這對客戶端或者說服務(wù)端統(tǒng)一網(wǎng)關(guān)的要求是必須支持sticky routing。假設(shè)客戶端連接斷了,接下來的必須重連之前的同一個服務(wù)器。微服務(wù)的stateless,水瓶擴展要求本身就是反sticky routing的,因為sticky routing本身就是狀態(tài)。
對服務(wù)端集群來說,同時有無數(shù)個王者榮耀的比賽在進行,每個都可以看成一個沙盒,每個沙盒都處于一個不同的狀態(tài):塔被推了幾個了,你被殺了幾次了,對面幾個超神了,20分鐘到了沒。

微服務(wù)本身是為了應(yīng)對業(yè)務(wù)邏輯的復(fù)雜,需要要的新的組織接口的方式。游戲本身邏輯其實沒有這么復(fù)雜,比如大廳就是一些基本功能,修改帳號,登錄等。游戲本身就是游戲本身的邏輯。
游戲邏輯服務(wù)器本身(比如斗地主等棋牌)因為網(wǎng)絡(luò)響應(yīng)性能要求問題(玩家對每個操作的反饋時長敏感度遠高于業(yè)務(wù)系統(tǒng)),所以游戲服務(wù)器都是有狀態(tài)的,狀態(tài)就存在內(nèi)存,偶爾會接受Redis,MySQL等是絕對不可以的接受的,關(guān)系行數(shù)據(jù)庫僅用來定時異步持久化數(shù)據(jù),僅游戲服務(wù)器而言持久化在Redis即可。
游戲服務(wù)器一般純需要主動推送,所以第一代微服務(wù)網(wǎng)關(guān)就沒辦法滿足需求, TCP的沒有網(wǎng)關(guān)用,Spring Cloud Gateway的Web socket也許可以用(但是從防攻擊角度講端游用TCP絕對比Web socket合理)。
服務(wù)間通信RPC首先Ribbon,F(xiàn)eign等并不是合適,因為都是基于http的,用http存在一個消息亂序問題,比如玩家出牌兩次,在http就可能出現(xiàn)次序不一致。游戲服務(wù)器集群一般使用長連接互聯(lián)??赡苄枰肈ubbo?(聽說是長連接)
游戲邏輯服務(wù)器(比如斗地主服務(wù)器),一般是不能用Spring MVC做的,因為線程模型完全不同。多線程模型處理游戲性能差還非常復(fù)雜,一般都是使用單進程/線程 驅(qū)動固定數(shù)量房間的方式(這也是為何服務(wù)器一定有狀態(tài),一定不能直接讀寫MySQL)。一般就直接Netty了。
自動擴容在游戲這邊叫做開服,早就有固定流程和工具和限流方式了。
游戲很多操作不存在服務(wù)降級熔斷,不行就要直接報錯給用戶。
大廳服務(wù)器登錄注冊等的確可以做微服務(wù),但是其實也不是做微服務(wù),就是幾個接口有自動水平擴容的方案即可。服務(wù)注冊發(fā)現(xiàn)用處不大,開服都是確定的事情,還有一系列運營手段配合,關(guān)服也是絕對不能隨便關(guān)的。
游戲處理的流量真的不算多,你在線1萬的棋牌游戲已經(jīng)很賺錢了,10W就是個特別厲害的產(chǎn)品了。
一些獨立的服務(wù)器比如充值之類的需要微服務(wù)化么?只能說這種服務(wù)器都需要微服務(wù)處理了,項目組做夢都能笑醒。

。。。有些國民級moba游戲的微服務(wù)化過程,可能有保密問題,我就不談了。
拿中年人喜聞樂見的WOW來說,你們不知道有專門的排隊服務(wù)器、場景服務(wù)器、副本服務(wù)器么這些么?你以為每次切換場景時的loading界面在做啥?就是完成service的切換啊。
你非要用web那一套來套在游戲上面,那當然不行,那說明你對microservice的理解太狹隘了。microservice重點是業(yè)務(wù)邏輯的拆分和獨立,難道你以為這么多mmorpg,是一個巨大無比的monolithic的應(yīng)用在跑?怎么可能。
多人游戲和互聯(lián)網(wǎng)app相比,最大的差別不是microservice還是monolithic,也不是啥實時還是非實時,而是stateful和stateless的差別?;ヂ?lián)網(wǎng)app大量的工作是在數(shù)據(jù)讀寫上,為了能瘋狂scale,service本身一般是stateless的,最簡單的一個例子就是web server的session概念(現(xiàn)在比較過時了,但是是個很好的例子),既可以本地,也可以存入redis或者db。游戲的server其實也是保存這樣一個當前場景涵蓋所有人的巨大session(比如副本,比如moba中的游戲全局狀態(tài))。由于游戲過程本身并沒有什么保存價值,所以對這些實時進行的游戲狀態(tài)進行持久化沒啥意義,因此才有專門的對戰(zhàn)服務(wù)器等等。
其實你把什么對戰(zhàn)服務(wù)器、排隊服務(wù)器、匹配服務(wù)器等等都叫做xx service,就會發(fā)現(xiàn)其實就是微服務(wù)概念。
補充一點個人不保證正確的私貨:其實整個游戲開發(fā)行業(yè)和互聯(lián)網(wǎng)行業(yè)的技術(shù)思維差異就在于stateful vs stateless,做習(xí)慣了游戲開發(fā)的人(無論客戶端還是backend),習(xí)慣了直接在內(nèi)存讀寫數(shù)據(jù),不習(xí)慣從遠程讀寫(無論是redis還是db或者nosql或者啥),換句話說他們不太習(xí)慣原始數(shù)據(jù)不在本地機器上,而恰恰業(yè)務(wù)邏輯和數(shù)據(jù)分離是互聯(lián)網(wǎng)架構(gòu)的重要指導(dǎo)思想。這使得游戲開發(fā)程序員的技術(shù)思維很有些不一樣,我不能說不好,但是確實有點技能點的配置不同的感覺,這當實現(xiàn)非游戲項目的時候是有障礙的。
評論中的朋友是一個較為典型的例子,始終固守在傳統(tǒng)(國內(nèi))對游戲單體開發(fā)的思路上,你當然可以這么做,但是不意味著就必須這么做,更不意味著這么做就是好的。
一開始我說的國民級游戲之一就是LOL,搜了一下公開資料,,發(fā)現(xiàn)他們也略微談過一點他們后臺微服務(wù)化的事情
不過他們也是比較含糊其辭的,沒談具體功能模塊劃分,只含糊舉了些抽象例子。所以為了避免有些問題,我也就不提了。
微服務(wù)本身就是個模塊化的概念,國內(nèi)喜歡眉毛胡子一把抓強調(diào)單機性能單機并發(fā)(實質(zhì)是發(fā)懶),而要把單體應(yīng)用的各種模塊分拆出來,問題主要是團隊管理、服務(wù)治理、開發(fā)協(xié)調(diào)、部署、功能邊界和定義這些微服務(wù)本身的坑。至于很多人說的性能、響應(yīng)速度等等,這些都是拆分時要考慮的因素之一罷了,并不是啥模塊都要糾結(jié)這些的。
對此你怎么看?
推薦閱讀
站長 polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場和創(chuàng)業(yè)經(jīng)驗
Go語言中文網(wǎng)
每天為你
分享 Go 知識
Go愛好者值得關(guān)注
