服務器端開發的一些建議

摘要: 本文作為游戲服務器端開發的基本大綱,是游戲實踐開發中的總結。第一部分專業基礎,用于指導招聘和實習考核, 第二部分游戲入門,講述游戲服務器端開發的基本要點,第三部分服務端架構,介紹架構設計中的一些基本原則。希望能幫到大家

一 專業基礎

1.1 網絡

1.1.1 理解TCP/IP協議
網絡傳輸模型
滑動窗口技術
建立連接的三次握手與斷開連接的四次握手
連接建立與斷開過程中的各種狀態
TCP/IP協議的傳輸效率
思考
1)請解釋DOS攻擊與DRDOS攻擊的基本原理
2)一個100Byte數據包,精簡到50Byte, 其傳輸效率提高了50%
3)TIMEWAIT狀態怎么解釋?
1.1.2 掌握常用的網絡通信模型
Select
Epoll,邊緣觸發與平臺出發點區別與應用
Select與Epoll的區別及應用
1.2 存儲
計算機系統存儲體系
程序運行時的內存結構
計算機文件系統,頁表結構
內存池與對象池的實現原理,應用場景與區別
關系數據庫MySQL的使用
共享內存
1.3 程序
對C/C++語言有較深的理解
深刻理解接口,封裝與多態,并且有實踐經驗
深刻理解常用的數據結構:數組,鏈表,二叉樹,哈希表
熟悉常用的算法及相關復雜度:冒泡排序,快速排序

二 游戲開發入門

2.1防御式編程
不要相信客戶端數據,一定要檢驗。作為服務器端你無法確定你的客戶端是誰,你也不能假定它是善意的,請做好自我保護。(這是判斷一個服務器端程序員是否入門的基本標準)
務必對于函數的傳人參數和返回值進行合法性判斷,內部子系統,功能模塊之間不要太過信任,要求低耦合,高內聚
插件式的模塊設計,模塊功能的健壯性應該是內建的,盡量減少模塊間耦合
2.2 設計模式
道法自然。不要迷信,迷戀設計模式,更不要生搬硬套
簡化,簡化,再簡化,用最簡單的辦法解決問題
借大寶一句話:設計本天成,妙手偶得之
2.3 網絡模型
自造輪子: Select, Epoll, Epoll一定比Select高效嗎?
開源框架: Libevent, libev, ACE
2.4 數據持久化
自定義文件存儲,如《夢幻西游》
關系數據庫: MySQL
NO-SQL數據庫: MongoDB
選擇存儲系統要考慮到因素:穩定性,性能,可擴展性
2.5 內存管理
使用內存池和對象池,禁止運行期間動態分配內存
對于輸入輸出的指針參數,嚴格檢查,寧濫勿缺
寫內存保護。使用帶內存保護的函數(strncpy, memcpy, snprintf, vsnprintf等),嚴防數組下標越界
防止讀內存溢出,確保字符串以’\0’結束
2.6 日志系統
簡單高效,大量日志操作不應該影響程序性能
穩定,做到服務器崩潰是日志不丟失
完備,玩家關鍵操作一定要記日志,理想的情況是通過日志能重建任何時刻的玩家數據
開關,開發日志的要加級別開關控制
2.7 通信協議
采用PDL(Protocol Design Language), 如Protobuf,可以同時生成前后端代碼,減少前后端協議聯調成本, 擴展性好
JSON,文本協議,簡單,自解釋,無聯調成本,擴展性好,也很方便進行包過濾以及寫日志
自定義二進制協議,精簡,有高效的傳輸性能,完全可控,幾乎無擴展性
2.8 全局唯一Key(GUID)
為合服做準備
方便追蹤道具,裝備流向
每個角色,裝備,道具都應對應有全局唯一Key
2.9 多線程與同步
消息隊列進行同步化處理
2.10 狀態機
強化角色的狀態
前置狀態的檢查校驗
2.11 數據包操作
合并, 同一幀內的數據包進行合并,減少IO操作次數
單副本, 用一個包盡量只保存一份,減少內存復制次數
AOI同步中減少中間過程無用數據包
2.12 狀態監控
隨時監控服務器內部狀態
內存池,對象池使用情況
幀處理時間
網絡IO
包處理性能
各種業務邏輯的處理次數
2.13 包頻率控制
基于每個玩家每條協議的包頻率控制,癱瘓變速齒輪
2.14 開關控制
每個模塊都有開關,可以緊急關閉任何出問題的功能模塊
2.15 反外掛反作弊
包頻率控制可以消滅變速齒輪
包id自增校驗,可以消滅WPE
包校驗碼可以消滅包攔截篡改
圖形識別嗎,可以踢掉99%非人的操作
魔高一尺,道高一丈
2.16 熱更新
核心配置邏輯的熱更新,如防沉迷系統,包頻率控制,開關控制等
代碼基本熱更新,如Erlang,Lua等
2.17 防刷
關鍵系統資源(如元寶,精力值,道具,裝備等)的產出記日志
資源的產出和消耗盡量依賴兩個或以上的獨立條件的檢測
嚴格檢查各項操作的前置條件
校驗參數合法性
2.18 防崩潰
系統底層與具體業務邏輯無關,可以用大量的機器人壓力測試暴露各種bug,確保穩定
業務邏輯建議使用腳本
系統性的保證游戲不會崩潰
2.19 性能優化
IO操作異步化
IO操作合并緩寫 (事務性的提交db操作,包合并,文件日志緩寫)
Cache機制
減少競態條件 (避免頻繁進出切換,盡量減少鎖定使用,多線程不一定由于單線程) 多線程不一定比單線程快
減少內存復制
自己測試,用數據說話,別猜
2.20 運營支持
接口支持:實時查詢,控制指令,數據監控,客服處理等
實現考慮提供Http接口
2.21 容災與故障預案

三 服務器端架構

3.1 什么是好的架構?
滿足業務要求
能迅速的實現策劃需求,響應需求變更
系統級的穩定性保障
簡化開發。將復雜性控制在架構底層,降低對開發人員的技術要求,邏輯開發不依賴于開發人員本身強大的技術實力,提高開發效率
完善的運營支撐體系
3.2 架構實踐的思考
簡單,滿足需求的架構就是好架構
設計性能,抓住重要的20%, 沒必要從程序代碼里面去摳性能
熱更新是必須的
人難免會犯錯,盡可能的用一套機制去保障邏輯的健壯性

游戲服務器的設計是一項頗有挑戰性的工作,游戲服務器的發展也由以前的單服結構轉變為多服機構,甚至出現了bigworld引擎的分布式解決方案,最近了解到Unreal的服務器解決方案atlas也是基于集群的方式。

負載均衡是一個很復雜的課題,這里暫不談bigworld和atlas的這類服務器的設計,更多的是基于功能和場景劃分服務器結構。

首先說一下思路,服務器劃分基于以下原則:

  1. 分離游戲中占用系統資源(cpu,內存,IO等)較多的功能,獨立成服務器。
  2. 在同一服務器架構下的不同游戲,應盡可能的復用某些服務器(進程級別的復用)。
  3. 以多線程并發的編程方式適應多核處理器。
  4. 寧可在服務器之間多復制數據,也要保持清晰的數據流向。
  5. 主要按照場景劃分進程,若需按功能劃分,必須保持整個邏輯足夠的簡單,并滿足以上1,2點。

服務器結構圖:

游戲服務器架構拓撲圖

各個服務器的簡要說明:

Gateway 是應用網關,主要用于保持和client的連接,該服務器需要2種IO,對client采用高并發連接,低吞吐量的網絡模型,如IOCP等,對服務器采用高吞吐量連接,如阻塞或異步IO。

網關主要有以下用途:

  1. 分擔了網絡IO資源
  2. 同時,也分擔了網絡消息包的加解密,壓縮解壓等cpu密集的操作。
  3. 隔離了client和內部服務器組,對client來說,它只需要知道網關的相關信息即可(ip和port)。
  4. client由于一直和網關保持常連接,所以切換場景服務器等操作對client來說是透明的。
  5. 維護玩家登錄狀態。

World Server 是一個控制中心,它負責把各種計算資源分布到各個服務器,它具有以下職責:

  1. 管理和維護多個Scene Server。
  2. 管理和維護多個功能服務器,主要是同步數據到功能服務器。
  3. 復雜轉發其他服務器和Gateway之間的數據。
  4. 實現其他需要跨場景的功能,如組隊,聊天,幫派等。

Phys Server 主要用于玩家移動,碰撞等檢測。

所有玩家的移動類操作都在該服務器上做檢查,所以該服務器本身具備所有地圖的地形等相關信息。具體檢查過程是這樣的:首先,Worldserver收到一個移動信息,WorldServer收到后向Phys Server請求檢查,Phys Server檢查成功后再返回給world Server,然后world server傳遞給相應的Scene Server。

Scene Server 場景服務器,按場景劃分,每個服務器負責的場景應該是可以配置的。理想情況下是可以動態調節的。

ItemMgr Server 物品管理服務器,負責所有物品的生產過程。在該服務器上存儲一個物品掉落數據庫,服務器初始化的時候載入到內存。任何需要產生物品的服務器均與該服務器直接通信。

AIServer 又一個功能服務器,負責管理所有NPC的AI。AI服務器通常有2個輸入,一個是Scene Server發送過來的玩家相關操作信息,另一個時鐘Timer驅動,在這個設計中,對其他服務器來說,AIServer就是一個擁有很多個NPC的客戶端。AIserver需要同步所有與AI相關的數據,包括很多玩家數據。由于AIServer的Timer驅動特性,可在很大程度上使用TBB程序庫來發揮多核的性能。

把網絡游戲服務器分拆成多個進程,分開部署。這種設計的好處是模塊自然分離,可以單獨設計。分擔負荷,可以提高整個系統的承載能力。

缺點在于,網絡環境并不那么可靠。跨進程通訊有一定的不可預知性。服務器間通訊往往難以架設調試環境,并很容易把事情攪成一團糨糊。而且正確高效的管理多連接,對程序員來說也是一項挑戰。

前些年,我也曾寫過好幾篇與之相關的設計。這幾天在思考一個問題:如果我們要做一個底層通用模塊,讓后續開發更為方便。到底要解決怎樣的需求。這個需求應該是單一且基礎的,每個應用都需要的。

正如 TCP 協議解決了互聯網上穩定可靠的點對點數據流通訊一樣。游戲世界實際需要的是一個穩定可靠的在游戲系統內的點對點通訊需要。

我們可以在一條 TCP 連接之上做到這一點。一旦實現,可以給游戲服務的開發帶來極大的方便。

可以把游戲系統內的各項服務,包括并不限于登陸,拍賣,戰斗場景,數據服務,等等獨立服務看成網絡上的若干終端。每個玩家也可以是一個獨立終端。它們一起構成一個網絡。在這個網絡之上,終端之間可以進行可靠的連接和通訊。

實現可以是這樣的:每個虛擬終端都在游戲虛擬網絡(Game Network)上有一個唯一地址 (Game Network Address , GNA) 。這個地址可以預先設定,也可以動態分配。每個終端都可以通過游戲網絡的若干接入點 ( GNAP ) 通過唯一一條 TCP 連接接入網絡。接入過程需要通過鑒權。

鑒權過程依賴內部的安全機制,可以包括密碼證書,或是特別的接入點區分。(例如,玩家接入網絡就需要特定的接入點,這個接入點接入的終端都一定是玩家)

鑒權通過后,網絡為終端分配一個固定的游戲域名。例如,玩家進入會分配到 player.12345 這樣的域名,數據庫接入可能分配到 database 。

游戲網絡默認提供一個域名查詢服務(這個服務可以通過鑒權的過程注冊到網絡中),讓每個終端都能通過域名查詢到對應的地址。

然后,游戲網絡里所有合法接入的終端都可以通過其地址相互發起連接并通訊了。整個協議建立在 TCP 協議之上,工作于唯一的這個 TCP 連接上。和直接使用 TCP 連接不同。游戲網絡中每個終端之間相互發起連接都是可靠的。不僅玩家可以向某個服務發起連接,反過來也是可以的。玩家之間的直接連接也是可行的(是否允許這樣,取決于具體設計)。

由于每個虛擬連接都是建立在單一的 TCP 連接之上。所以減少了互連網上發起 TCP 連接的各種不可靠性。鑒權過程也是一次性唯一的。并且我們提供域名反查服務,我們的游戲服務可以清楚且安全的知道連接過來的是誰。

系統可以設計為,游戲網絡上每個終端離網,域名服務將廣播這條消息,通知所有人。這種廣播服務在互聯網上難以做到,但無論是廣播還是組播,在這個虛擬游戲網絡中都是可行的。

在這種設計上。在邏輯層面,我們可以讓玩家直接把聊天信息從玩家客互端發送到聊天服務器,而不需要建立多余的 TCP 連接,也不需要對轉發處理聊天消息做多余的處理。聊天服務器可以獨立的存在于游戲網絡。也可以讓廣播服務主動向玩家推送消息,由服務器向玩家發起連接,而不是所有連接請求都是由玩家客互端發起。

虛擬游戲網絡的構成是一個獨立的層次,完全可以撇開具體游戲邏輯來實現,并能夠單獨去按承載量考慮具體設計方案。非常利于剝離出具體游戲項目來開發并優化。

最終,我們或許需要的一套 C 庫,用于游戲網絡內的通訊。api 可以和 socket api 類似。額外多兩條接入與離開游戲網絡即可。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444977.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444977.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444977.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode63 不同路徑II

一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。 現在考慮網格中有障礙物。那么從左上角到右下角將…

小談Online-game服務器端設計(1、2)

談這個話題之前,首先要讓大家知道,什么是服務器。在網絡游戲中,服務器所扮演的角色是同步,廣播和服務器主動的一些行為,比如說天氣,NPC AI之類的,之所以現在的很多網絡游戲服務器都需要負擔一些…

Linux(8)-Linux下的編程開發-C/C++、PHP、JAVA概述

Linux下的編程開發1.C/C語言開發環境的搭建2.PHP開發環境搭建3.JAVA開發環境搭建1.C/C語言開發環境的搭建 方式1:文本編輯器編譯器(gcc/g) Ubuntu 下常用的文本編輯器: Gedit–語法高亮Vim–vi(無比強大無比難用)的改進。字符界面/圖形界面…

leetcode55 跳躍游戲 秒殺所有答案

給定一個非負整數數組,你最初位于數組的第一個位置。 數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個位置。 示例 1: 輸入: [2,3,1,1,4] 輸出: true 解釋: 我們可以先跳 1 步,從位置 0 到達 位置 1, 然后再從位置 …

小談Online-game服務器端設計(3)

下面我想來談談關于服務器上NPC的設計以及NPC智能等一些方面涉及到的問題。首先,我們需要知道什么是NPC,NPC需要做什么。NPC的全稱是(Non-Player Character),很顯然,他是一個character,但不是玩…

小談Online-game服務器端設計(4)

在這一章節,我想談談關于服務器端的腳本的相關設計。因為在上一章節里面,談NPC智能相關的時候已經接觸到一些腳本相關的東東了。還是先來談談腳本的作用吧。   在基于編譯的服務器端程序中,是無法在程序的運行過程中構建一些東西的&#xf…

leetcode45 跳躍游戲II 秒殺所有答案

給定一個非負整數數組,你最初位于數組的第一個位置。 數組中的每個元素代表你在該位置可以跳躍的最大長度。 你的目標是使用最少的跳躍次數到達數組的最后一個位置。 示例: 輸入: [2,3,1,1,4] 輸出: 2 解釋: 跳到最后一個位置的最小跳躍數是 2。 從下標為 …

MachineLearning(7)-決策樹基礎+sklearn.DecisionTreeClassifier簡單實踐

sklearn.DecisionTreeClassifier決策樹簡單使用1.決策樹算法基礎2.sklearn.DecisionTreeClassifier簡單實踐2.1 決策樹類2.3 決策樹構建2.3.1全數據集擬合,決策樹可視化2.3.2交叉驗證實驗2.3.3超參數搜索2.3.4模型保存與導入2.3.5固定隨機數種子參考資料1.決策樹算法…

游戲服務器體系結構

本文描述了一個我所設計的游戲服務器體系結構,其目的是實現游戲服務器的動態負載平衡,將對象從繁忙的服務器轉移到相對空閑的服務器中.設計并沒有經過具體的測試與驗證,僅僅是將自己目前的一些想法記錄下來.隨著新構思的出現,可能會有所變化. 以下是服務器的邏輯視圖,其中忽略…

游戲服務器架構探討

要描述一項技術或是一個行業,一般都會從其最古老的歷史開始說起,我本也想按著這個套路走,無奈本人乃一八零后小輩,沒有經歷過那些苦澀的卻令人羨慕的單機游戲開發,也沒有響當當的拿的出手的優秀作品,所以也…

leetcode72 編輯距離

給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少操作數 。 你可以對一個單詞進行如下三種操作: 插入一個字符 刪除一個字符 替換一個字符 示例 1: 輸入: word1 "horse", word2 "ros" 輸出: 3 解釋: ho…

即時通訊系統架構

有過幾款IM系統開發經歷,目前有一款還在線上跑著。準備簡單地介紹一下大型商業應用的IM系統的架構。設計這種架構比較重要的一點是低耦合,把整個系統設計成多個相互分離的子系統。我把整個系統分成下面幾個部分:(1)狀態…

leetcode303 區域和檢索

給定一個整數數組 nums,求出數組從索引 i 到 j (i ≤ j) 范圍內元素的總和,包含 i, j 兩點。 示例: 給定 nums [-2, 0, 3, -5, 2, -1],求和函數為 sumRange() sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0,…

算法(24)-股票買賣

股票買賣1.動態規劃框架LeetCode-121 一次買賣LeetCode-122 不限次數LeetCode-309 不限次數冷凍期LeetCode-714 不限次數手續費LeetCode-123 兩次買賣LeetCode-188 k次買賣2.貪心特解LeetCode-121 一次買賣LeetCode-122 不限次數解題思路參考buladong解題,詳細信息可…

網絡游戲的客戶端同步問題 .

有關位置同步的方案實際上已經比較成熟,網上也有比較多的資料可供參考。在《帶寬限制下的視覺實體屬性傳播》一文中,作者也簡單提到了位置同步方案的構造過程,但涉及到細節的地方沒有深入,這里專門針對這一主題做些回顧。 最直接的…

leetcode319 燈泡的開關

初始時有 n 個燈泡關閉。 第 1 輪,你打開所有的燈泡。 第 2 輪,每兩個燈泡你關閉一次。 第 3 輪,每三個燈泡切換一次開關(如果關閉則開啟,如果開啟則關閉)。第 i 輪,每 i 個燈泡切換一次開關。 …

網游服務器端設計思考:心跳設計

網絡游戲服務器的主要作用是模擬整個游戲世界,客戶端用過網絡連接把一些信息數據發給服務器,在操作合法的情況下,更新服務器上該客戶端對應的player實體、所在場景等,并把這些操作及其影響廣播出去。讓別的客戶端能顯示這些操作。…

算法(25)-括號

各種括號1.LeetCode-22 括號生成--各種括號排列組合2.LeetCode-20 有效括號(是否)--堆棧3.LeetCode-32 最長有效括號(長度)--dp4.LeetCode-301刪除無效括號 --多種刪除方式1.LeetCode-22 括號生成–各種括號排列組合 數字 n 代表生成括號的對數,請你設計一個函數&a…

(二十)深入淺出TCPIP之epoll的一些思考

Epoll基本介紹 在linux的網絡編程中,很長的時間都在使用select來做事件觸發。在linux新的內核中,有了一種替換它的機制,就是epoll。相比于 select,epoll最大的好處在于它不會隨著監聽fd數目的增長而降低效率。因為在內核中的select實現中,它是采用輪詢來處理的,輪詢的fd…

leetcode542 01矩陣

給定一個由 0 和 1 組成的矩陣,找出每個元素到最近的 0 的距離。 兩個相鄰元素間的距離為 1 。 示例 1: 輸入: 0 0 0 0 1 0 0 0 0 輸出: 0 0 0 0 1 0 0 0 0 示例 2: 輸入: 0 0 0 0 1 0 1 1 1 輸出: 0 0 0 0 1 0 1 2 1 注意: 給定矩陣的元素個數不超過 10000。…