筆者十年前做過網絡游戲,當第一次看到微服務架構就發現它和網絡游戲架構很像,如下圖:
先來簡單介紹一下這個網游架構,有些東西記不清了,如今的網游大牛看到可別丟磚頭。
用戶下載網游客戶端,登錄網游,首先會執行登錄服務,登錄服務主要就是給你分配一個網關,因為網關后面連接的才是真正的游戲服務器。登錄后,進入游戲,發出指令,比如你移動到某個位置,這個指令會先發送到網關,然后再由網關識別發送到“移動系統”服務,移動系統計算后再經由網關發送給玩家客戶端,玩家客戶端執行一個動畫讓你移動到某個位置。
假如子服務間要通信也是通過網關轉發,比如任務系統里面要購買物品,那么任務系統發一個指令消息給網關,網關再轉發給物品系統等等。圖中的“游戲A服務器集群”,其中“游戲A”代表你所屬的游戲服務器,每個游戲服務器能承載的人數是有限的(當時的技術一個服務器組最多同時在線也就幾千人),人數滿了,你就要登錄到另外的服務器。“集群”表示服務部署的集群。每一個明面上的游戲服務器,對應一個N台服務器構成的游戲服務集群,但只對應一個用戶數據庫,數據庫沒有使用集群技術,因為你即使使用了數據庫集群技術,在實時性方面也跟不上。
從編程上來講,包括以下應用:
客戶端.exe
網關.exe
移動系統.exe
聊天系統.exe
….
說到這里,了解微服務的人可能看出來了,上面的網關就好比nginx反向代理服務器,每一個游戲服務就好比微服務中的服務,如果你的微服務通信協議使用的是TCP那后面服務部分基本就一模一樣了。網絡游戲中數據訪問沒有分層直接放到業務處理模塊,在游戲中每一個游戲執行邏輯不管是加載腳本、配置數據還是賬戶數據都是在同一個邏輯中處理的,不會去划分出什么數據庫訪問層、腳本訪問層,這樣處理有一個很大的好處,那就是可以處理復雜的邏輯,而又不用喪失效率。
在網游中,因為服務間通信的是二進制消息,在編程時解析消息和組裝消息非常麻煩,因此需要設計一個統一的類庫,這個類庫把二進制消息傳遞直接變成面向對象調用。比如你調用了一個方法,其實就是向網關發送了一個二進制消息。這用在微服務這里也是一樣的,讓接口的收發消息變成面向對象調用,可以提高編程開發的效率,又能降低通信所產生的bug,孢子框架中的接口訪問層也完成類似功能。
至於說分布式事務的問題,在網游開發中比較容易就可以解決(即使解決不了還有客服),因為所有事物相關數據都在一個數據庫,即使不在一個數據庫也是通過消息去同步。比如你砍了怪物一刀,你的等級數據上升、體力下降都在一個服務里計算的,假如怪物被砍了一刀的計算不在這個服務里,那么會發一個消息給那個服務,那個服務計算怪物被砍了一刀,如果計算失敗,再回發一個消息給前一個服務來協同這方面,如果被砍死了掉物品了,就發一個消息給物品服務去計算,物品服務再回發消息與主計算協同。這其實就是通過消息機制進行事務協同最原始的版本。
和微服務對比歸納一下:
游戲(Gate網關)相當於:微服務(nginx或API Gateway)
游戲(個體服務)相當於:微服務(個體服務)
游戲(接口訪問層)相當於:孢子框架(接口訪問層)
另外微服務中流行的分布式事務解決方法也是通過消息來實現,比如支付,調用方調用支付接口失敗,發一個失敗消息給消息隊列,支付接口服務監聽消息隊列並處理支付失敗。
補充:少了場景服務,場景服務管理進入某地圖的所有資源,比如一個人要移動,計算完個人移動后,還要向地圖內(可視范圍內)所有人發送移動消息。