本文作者:sodme 本文出處:http://blog.csdn.net/sodme
著作權聲明:本文可以不經作者同意任意轉載,但轉載時煩請保留文章開始前兩行的著作權、作者及出處資訊。
提示:閱讀本文前,請先讀此文瞭解文章背景:http://data.gameres.com/message.asp?TopicID=27236
讓無數中國玩家為之矚目的“魔獸世界”,隨著一系列內測前期工作的逐步展開,正在一步步地走近中國玩家,但是,“魔獸”的伺服器,卻著實讓我們為它捏了一把汗。
造成一個網遊伺服器當機的原因有很多,但主要有以下兩種:一,伺服器線上人數達到上限,伺服器處理效率嚴重遲緩,造成當機;二,由於外掛或其它遊戲作弊工具導致的非正常資料包的出錯,導致遊戲伺服器邏輯出現混亂,從而造成當機。在這裡,我主要想說說後者如何儘可能地避免。
要避免以上所說到的第二種情況,我們就應該遵循一個基本原則:在網遊伺服器的設計中,對於具有較強邏輯關係的處理單元,伺服器端和用戶端應該採用“互不信任原則”,即:伺服器端即使收到了用戶端的資料包,也並不是立刻就認為用戶端已經達到了某種功能或者狀態,用戶端到達是否達到了某種功能或者狀態,還必須依靠伺服器端上記載的該用戶端“以往狀態”來判定,也就是說:伺服器端的邏輯執行並不單純地以“當前”的這一個用戶端封包來進行,它還應該廣泛參考當前封包的上下文環境,對執行的邏輯作出更進一步地判定,同時,在單個封包的處理上,伺服器端應該廣泛考慮當前用戶端封包所需要的“前置”封包,如果沒有收到該用戶端應該發過來的“前置”封包,則當前的封包應該不進行處理或進行異常處理(如果想要效能高,則可以直接忽略該封包;如果想讓伺服器穩定,可以進行不同的異常處理)。
之所以採用“互不信任”原則設計網遊伺服器,一個很重要的考慮是:防外掛。對於一個網路伺服器(不僅僅是遊戲伺服器,泛指所有伺服器)而言,它所面對的對象既有屬於自己系統內的合法的網路用戶端,也有不屬於自己系統內的非法用戶端訪問。所以,我們在考慮伺服器向外開放的介面時,就要同時考慮這兩種情況:合法用戶端訪問時的邏輯走向以及非法用戶端訪問時的邏輯走向。舉個簡單的例子:一般情況下,玩家登入邏輯中,都是先向伺服器發送使用者名稱和密碼,然後再向伺服器發送進入某組伺服器的資料包;但在非法用戶端(如外掛)中,則這些用戶端則完全有可能先發進入某組伺服器的資料包。當然,這裡僅僅是舉個例子,也許並不妥當,但基本的意思我已經表達清楚了,即:你伺服器端不要我用戶端發什麼你就信什麼,你還得進行一系列的邏輯驗證,以判定我當前執行的操作是不是合法的。以這個例子中,伺服器端可以通過以下邏輯執行驗證功能:只有當用戶端的使用者名稱和密碼通過驗證後,該用戶端才會進入線上玩家列表中。而只有線上玩家列表中的成員,才可以在登陸伺服器的引導下進入各分組伺服器。
總之,在從事網遊伺服器的設計過程中,要始終不移地堅持一個信念:我們的伺服器,不僅僅有自己的遊戲用戶端在訪問,還有其它很多他人寫的遊戲用戶端在訪問,所以,我們應該確保我們的伺服器是足夠強壯的,任它風吹雨打也不怕,更不會倒。如果在開發實踐中,沒有很好地領會這一點或者未能將這一思路貫穿進開發之中,那麼,你設計出來的伺服器將是無比脆弱的。
當然,安全性和效率總是相互對立的。為了實現我們所說的“互不信任”原則,難免的,就會在遊戲邏輯中加入很多的異常檢測機制,但異常檢測又是比較耗時的,這就需要我們在效率和安全性方面作個取捨,對於特別重要的邏輯,我們應該全面貫徹“互不信任”原則,一步扣一步,步步為營,不讓遊戲邏輯出現一點漏洞。而對於並非十分重要的場合,則完全可以採用“半信任”或者根本“不須信任”的原則進行設計,以儘可能地提高伺服器效率。
本文只是對自己長期從事遊戲伺服器設計以來的感受加以總結,也是對魔獸的伺服器有感而發。歡迎有相同感受的朋友或從事相同工作的朋友一起討論。