五星宏輝游戲項目小結
web服務端和game服務端的區別
Server的定義和分類
wiki對Server的定義:
In computing, a server is a computer program or a device that provides functionality for other programs or devices, called "clients". This architecture is called the client–server model, and a single overall computation is distributed across multiple processes or devices.
**分類:Typical servers are **
- Database Server
- File Server
- Mail Server
- Print Server
- Web Server
- Game Server
- Application Server
異同
Web Server,典型例子是淘寶。
特點:
- 所有流程均由客戶端發起,客戶端發個請求,服務端返回個響應——請求響應模式
- 根據客戶端訪問的服務不同,客戶端可以向不同的具體服務端節點發起請求
Game Server,典型例子是魔獸世界。
特點:
- 有一個肉眼能感覺到的連接握手的過程,建立連接后,流程有可能是服務端發起(比如給你展示周邊玩家),也有可能是客戶端發起(比如你移動了一下)——交互性
- 同時,如果你手邊有抓包工具,可以看到,如果你選中了某個玩家,在該玩家的頭像框消失之前,一直是同一個場景服務器在跟你通信。——常連接
Application Server,典型例子是QQ。
特點:
- 介於Web Server和Game Server之間,看着像一個web服務器,但是又有游戲服務器的特點。
服務端在client-server模型中的扮演角色:
服務端,在物理上表現為一或多台主機,在邏輯上向客戶端暴露一組host:port二元組,接受客戶端連接,為每個客戶端連接維持連接會話(Session)。客戶端與服務端借助連接會話傳遞消息,消息按一定的協議序列化與反序列化,客戶端與服務端的邏輯模塊由消息的內容驅動運轉。
不論是Web Server,還是Game Server,在運作流程上都大體相同。而在流程中的細節上,有共同點,也有不同點。下面就分開說道說道。
共同點:
-
都是為客戶端提供多種服務
-
比如淘寶既提供搜索服務,又提供商品頁查詢服務。
魔獸世界既提供登錄服務,又提供讓你在場景里戰斗、走跑跳的服務。
-
-
都需要連接會話概念
-
會話是建立在連接之上的概念,其實本質上是服務端為某個特定客戶端維持的數據結構與狀態信息。
Game Server自不必說,玩家登錄之后,服務端需要有一個專門的全局服務器維護玩家狀態與玩家的部分較熱的存檔信息,玩家進入到某個場景,場景服務器還需要專門維護一份玩家的場景相關的狀態信息。
Web Server,連接會話同樣存在,最直觀的理解是淘寶登錄之后服務端會為客戶端保持一個會話上下文。
-
-
服務端的每台物理機服務多個客戶端
- 這是服務器的誕生基礎,發展到現在,已經沒人再討論是異步IO還是多路復用,現在成熟的解決方案已經不存在孰優孰劣的問題,完全是哪個網絡庫用的順手就默認接受這個網絡庫底層的IO模型。
-
都具有分布式結構
-
架構的演化總是相似的,Web服務端與游戲服務端在發展過程中相互學習相互演進,目前形成的主流架構基本都至少應該將專門管連接的、專門管邏輯、專門管存儲的做一定程度的物理隔絕。
可以像skynet一樣,利用luaState做隔絕;可以像Erlang一樣,利用actor做隔絕;也可以最簡單的,按進程隔絕。只要能保證其中之一掛掉不會產生連鎖反應導致其他都掛掉就可以了。
-
-
開發語言
-
實際上也是近幾年手游開發火起來之后開發語言才趨於統一的。web開發一直是百家爭鳴,而游戲開發在以前是C++一家獨大。
但是現在,客戶端的邏輯層已經基本見不到C++的影子了,服務端純用C++的也越來越少了。lua、python、java、C#、Erlang、js甚至ruby的工業級游戲服務端框架都有出現,web服務端和游戲服務端的開發語言已經趨同。
-
不同點:
-
會話的存在形式(本質區別)
-
這一點是web服務端與游戲服務端最本質的區別
web服務端的客戶端與客戶端之間交互非常有限,因此,服務端可以將會話狀態保存在外部存儲服務,比如一些緩存中間件、文件系統中間件,然后等再用到的時候再拿出來就可以了。
而游戲服務端的客戶端與客戶端之間交互非常頻繁,比如,同場景的其他玩家會不停做不規律移動,戰斗時一個技能就會對復數個玩家造成影響。
這時如果將會話狀態保存在外部,會造成頻繁的狀態存取,嚴重影響服務器吞吐量。因此對於游戲服務端來說,會話通常保存在進程內。
-
-
交互頻率與數據流向
-
Web Server的頻率低,而且數據的流動是由客戶端驅動的,流向通常是客戶端請求了,服務端才返回。
Game Server的頻率高,數據的流動一部分由客戶端驅動,一部分由服務端驅動。流向除了服務端對客戶端請求的響應,還有服務端的主動推送。
-
-
通信協議基礎
-
通信協議基礎就是客戶端和服務端通信的協議所依賴的協議基礎。
按常識理解的話,web通信的基礎在應用層是http協議。由於小說君對web開發並不太熟悉,所以不太清楚目前私有協議在web開發中的應用,但是想必即使是私有協議,也一定是套在http協議的某些字段里面的,這跟游戲的客戶端服務端通信有本質區別。
游戲通常會實現私有的序列化協議,可以簡單理解為應用層定義協議包結構平鋪成字節流或者是串行序列化字節流。如果要支持一定程度的協議版本兼容,會用二進制json或者protobuf來實現協議序列化,但是通信協議本身是沒有「基礎」可言的,純私有化協議,不具普適性,也沒有必要定義成一種專門的協議。
-
-
對第三方組件的依賴程度
-
web服務端發展速度快,從業者多,同技術棧的從業者交流更深入更頻繁。因此,web服務端出現、並且還會出現越來越多的第三方獨立組件。web服務端的從業者甚至只需要在自己的技術棧不同層次上選擇不同的第三方組件,黏合起來,就能形成一整套的解決方案,非常方便。
游戲服務端正相反,比較封閉,基本上每個項目組要么是從頭到尾重寫,要么是從其他項目組拿來整套技術棧直接改改。基本不存在第三方獨立組件的情況,在技術開放氛圍好些的公司還好,畢竟大家可以復用同一套框架,否則的話,公司內的框架多種多樣,各種造輪子出來的,各種空降團隊從原來公司帶過來的,技術無法復用,團隊成員流動更是一大難題。
-
Firefly框架
在游戲服務器端,往往需要處理大量的各種各樣的任務,每一項任務所需的系統資源也可能不同。而這些復雜的任務只用一個單獨的服務器進程是很難支撐和管理起來的。所以,游戲服務器端的開發者往往需要花費大量的時間精力在諸如服務器類型的划分,進程數量的分配,以及這些進程的維護,進程間的通訊,請求的路由等等這些底層的問題上。而Firefly完全可以完成這些重復而繁瑣的工作,從而將上層的游戲開發者解放出來,把精力更多的放在游戲邏輯的實現上面。
Firefly是免費、開源、穩定、快速擴展、能“熱更新”的分布式游戲服務器端框架,采用Python編寫,基於Twisted框架開發。
Firefly特性
- 采用單線程多進程架構,支持自定義的分布式架構
- 方便的服務器擴展機制,可快速擴展服務器類型和數量
- 與客戶端采用TCP長連接,無需考慮粘包等問題
Firefly思路
一個最基本的服務器就是一個在不停運行着的應用程序。
在分布式游戲服務器中,我們需要的服務器具有的功能有:
- 監聽客戶端的連接
- 監聽其它服務進程的消息
- 連接其它服務進程
- 數據庫連接和緩存服務
Net connect 做客戶端連接
Root監聽其他服務進程消息
Node連接其他服務進程,db數據庫,cache緩存
是否需要監聽客戶端連接,是否監聽其他服務進程消息等這是都是可以在config.json中進行配置。包括各個服務器的名稱以及各個服務器之間的連接關系。這樣就可以自定義出自己的分布式架構。
Firefly結構
從功能職責上來看,Firefly框架結構如下圖所示:
- management:Firefly 是個多進程、分布式的游戲服務器。因此各游戲server(進程)的管理和擴展是firefly很重要的部分,框架通過抽象使服務器的擴展非常容易。
- Network:客戶端連接通信、server進程間的通信等構成了整個游戲框架的脈絡,所有游戲流程都構建在這個脈絡上。與客戶端的通信采用的是請求/響應式的,所有收到的客戶端的請求,服務端都會給出相應的回應,服務端也能主動的推送,廣播給客戶端消息。這些請求是基於指令號的請求(例如定義101為登陸指令)。server進程之間的通信時采用的異步回調的方式,這樣就減少了的進程間通過網絡通信中的時間消耗。
- Data: 數據處理是網游的重要部分。在網游有大量的數據需要存儲,需要更新,這使得數據庫的讀寫效率成為服務器的最大的性能瓶頸。Firefly的db處理能夠將數據庫表中的數據緩存到memcache中並能以對象的形式進行調用相應的對象方法對數據進行操作。可以在不同的進程中通過實例化相同的名稱的緩存實例,得到同步的數據。並能將緩存對象中的數據寫回數據庫中。
Firefly流程
- 從config.json中讀取配置數據
- 根據配置中定義的服務端的架構,啟動相應的服務進程。並建立節點之間的連接。有配置數據庫的,實例化數據庫連接池。有配置memcached的,建立memcached的連接。
- 根據配置相應的的進程啟動的入口模塊。
Python游戲后端架構
設計方案
- 性能卓越和高可用性
- 分布式架構(客戶端到服務端所有環節避免單點問題、有效負載均衡)
- 支持高並發寫(db緩存,部分模塊改為批量操作,減緩DB壓力)
- 游戲推送機制可靠快速,無延遲
- 分布式代理,故障發生時自動切換
- 游戲服務熱更新
- DDos防護
- 監控運維
- 用戶行為模擬(開發實現模擬大量真實用戶行為機器人程序)
- 通知模塊(獨立語音、短信、郵件通知服務模塊)
- 游戲異常監控系統(異常出現時實時通知相關人員)
- Linux上線操作腳本自動化,遠程部署
- ELK體系(引入kafka、elasticsearch、kibana,記錄分析游戲日志信息)
總體架構
Web服務代碼架構
預警系統體系
Client端(各待預警的子項目)數據上報(只需1步):
- 在用戶操作的前后調用已經封裝好的日志agent上報原始操作的信息(信息格式參考后續的接口文檔);
Server端(分析預警系統):
- 收到client發送過來的請求后,首先進行鑒權驗證;
- 驗證通過后,根據類型(異常錯誤類和信息記錄類)分類存儲到不同的消息隊列;
異常錯誤類:上報過來的信息一般為需要進行預警通知,錯誤的驗證邏輯由上報者自己內部判斷;
信息記錄類:上報者只是上報原始記錄信息,具體是否觸發預警的邏輯驗證由預警后台程序驗證;
- 不同類型的worker持續從對應的消息隊列中獲取最新消息,產生分析結果;
- 根據分析結果決定是否調用Notice服務通知產品開發、運營人員;
周期性任務:
該部分主要指預警后台周期性(天/小時/分鍾)執行各種統計分析任務,對可能出現異常的分析結果進行預警;某種程度上可以很好的起到數據埋點實時預警的第二道保障作用;
預警系統主體表結構設計: