當我設計遊戲服務器時,我在想些什麼?(2)

半年前我參與了一個手遊項目,第一次能夠主導整個遊戲的設計,這篇文章單說服務器的架構,客戶端就不提了。


對於服務端,我想從之前的端遊服務器改過來肯定是走不通的(詳見:),因爲手遊的開發週期比端遊短很多,上面那一套架構開發了5年不止,當然,期間推翻重做了很多次。而這個手遊項目只有快則6個月,慢則10個月的時間。


既然決定不用端遊的架構,一切從0開始,那麼快速搭建起一個可用的服務器是我考慮的第一個原則,第二點就是我做爲程序員的一點私心,儘量使用以前沒有用過的技術,這樣自己能夠接觸更廣闊的世界。

首先當然需要找找看有沒有現成的輪子,我花了1個月的時間,去尋找github上那些不錯的開源架構,其中有兩套系統我覺得很有潛力,一套是網易的pomelo,另一套是雲風的skynet。其實我首先知道的是skynet,因爲一直關注雲風的博客,所以他的這個服務端我還是有所瞭解的,我花了一週的時間詳細閱讀了skynet的wiki,並上手安裝了skynet,又寫了幾個簡單的http通信的例子,然後仔細分析了一下skynet中c模塊的寫法,甚至連如果要使用skynet,我的後臺部署圖會是什麼樣的都畫好了,不過最後還是放棄了skynet,理由是當時已經確定了前端會用cocos2dx+lua的組合來寫,我很想嘗試看看,客戶端和服務端的腳本語言不同會是個什麼樣子,同時,我還覺得,雲風用c的消息隊列,我還吃不透,而且當時skynet的用戶還不多,沒有先驅可以參照,skynet本身也還沒有穩定下來,雲風是個精力旺盛的傢伙,更新速度太快了。現在skynet已經發布了1.0了,下個遊戲很有可能我會用它。


然後我發現了node.js,其實也不能說是我發現的,公司有前輩已經開始用node.js做遊戲了,我當時比較好奇,於是看了一下nodejs的網站,又看了下網上的言論,覺得這貨很神奇,單線程的事件驅動,感覺比較簡單。接着pomelo就進入了視野,我居然發現網易開源了一個nodejs寫的遊戲服務器架構,真是喜從天降,我花了2周時間搭建,學習,測試pomelo的各種使用方法,用它copy了一個網上的聊天室代碼,期間遇到很多問題,我提的issue基本上沒有人問津,加入pomelo開發的qq羣開發者也是寥寥無幾,而且網易的人問題回饋的速度讓人哭,並是一副高高在上,對問題不做任何解釋的姿態出現的。我修改了幾個pomelo的問題後就放棄了它。但是不得不說,pomelo對我後面自己設計基於nodejs的服務器架構幫助很大,我有很大一部分設計是參考了它的想法,也是它引我進入了nodejs的世界。


在我花了將近1個月的時間,卻什麼都沒有收穫的時候,我決定找人聊一聊,我請教了很多前輩和厲害的朋友,他們給出了很多建議和幫助,也漸漸幫我理清了我到底需要做什麼。但一開始寫代碼,我就緊張。我不想走彎路,想要一開始就走在正確的道路上,我害怕走了很遠,結果發現是錯的,寫任何一行代碼,我都壓力倍增。那段時間,我痛苦,糾結,壓力極大,咬手指,我壓力一大就彎曲右手食指,然後用牙咬食指的第二和第三個關節,夜不能寐。終於有一天,我的好朋友XY說了一句話,讓我幡然醒悟,他說“先開始寫的,後面再慢慢改,哪有一開始就設計好的系統”。這麼簡單的一個道理,我聽過無數次,卻從來沒有領悟是什麼意思,這次真的被震動到了,確實,我想要一開始就走在正確的路上的做法明顯太天真了,而我更沒有必要爲走錯而懊惱,舉步維艱,是因爲我看得不夠遠。


於是,我開始動手了。


之前我倒是用過js,不過僅限於用 js 和 html 配合來製作網頁,這次拿來寫服務器,我是一點把握也沒有,首先從語言開始學起,我在網上看了很久的資料,最後買了2本書,一本是 crockford 的《javascript語言精粹》,另一本是樸靈的《深入淺出nodejs》,前一本是 js 中服務器要用到的那部分,js 語言其實有三部分組成,dom + bom + 基本核心,dom是操縱頁面元素的,bom 是操縱瀏覽器的,基本核心是語言的最基礎的部分,而服務器正好只需要這部分,crockford 的書寫的非常不錯,我很快就看懂了,然後我花了幾天時間整理了一份文檔,專門講解 js 語言的基本核心部分,用它來給我的另一個程序員朋友講,他從來沒有用過 js,我的目標是想把他講懂,那麼我肯定就理解透徹了,不過好像最後他也不太懂。。。


接着是 nodejs 的部分,樸靈大神寫的書的確不錯,應該是我看到的講解 nodejs 的書裏最優秀的那一類,按照他的書和nodejs官網的api文檔,我開始寫我的服務器了,按照我朋友的提醒,我首先寫一個單進程的服務器,而服務器最主要的部分就是網絡了,所以我先用 nodejs 的 net.socket 寫了一個tcp的服務器,這隻用十幾行代碼,nodejs 的 api 設計的非常不錯,而且文檔寫的也很好,很快就理解了,而且我給 nodejs 提的 issue 很快就會得到回覆,這期間我還發現 nodejs 對於 tpc,不過當時發現 nodejs 分家了還是小小擔心了一下的,不過現在又合併了:)


一開始,我打算模仿 pomelo 的架構,把它的那些我不需要的東西剔除出去,不過後來我放棄了,這件事情並不那麼容易,我還是老老實實從一個簡單的通信開始寫起,一開始我就想走多進程的路子,而且我認爲這也是必須的(但是現在我不這麼認爲了),但是一開始並不那麼好寫,步子邁的大了,容易扯到蛋。XY又提醒我,還是從單進程開始設計比較好,我接受了他的意見,在這個 tcp 服務器的基礎上慢慢的增加我認爲遊戲所必須的內容,例如數據庫接口、協議、網絡。基本上數據庫+網絡+協議就是一個完整的服務器了,其他的遊戲邏輯都是可以後來慢慢鋪的,正好這個時候客戶端的開發也開始了,我就用 luasocket 寫了一個簡單的客戶端網絡庫,拿來和我的這個單進程的服務器進行通信,終於,我的服務器跑起來了,代碼很少,我控制的住,我感覺非常開心:https://github.com/rangercyh/nodejs_server


這個服務器只具備最基本的能力,和數據庫能夠通信,使用 tcp 和客戶端進行通信,協議也是用的我自己設計的協議在通信,這裏不得不說一下,一開始我是打算用 protobuf 協議來通信的,後來放棄了,因爲我發現 protobuf 的 nodejs 綁定的庫接口設計的非常繁複,很難用。而且我沒有那麼高的需求,於是就自己實現協議了,後來我才發現,其實我完全可以用 json 格式就好,不過 lua 這邊處理 json 還有各種問題,這個後面我也會提到,這也是我之前說過,想嘗試一下客戶端和服務端使用不同語言的第一個代價。協議的解析要寫兩套,而且保證不出問題還是很困難的。


下一篇我會介紹一個很神奇的輪子:)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章