使用 Go 語言開發大型 MMORPG 遊戲伺服器怎麼樣?

和C Socket伺服器比起來有什麼優劣?可行性怎麼樣?


從2013年起,經朋友推薦開始用Golang編寫遊戲登陸伺服器, 配合C++做第三方平台驗證. 到編寫獨立工具導表工具GitHub - davyxu/tabtoy: 跨平台的高性能便捷電子表格導出器. 以及網路庫GitHub - davyxu/cellnet: 簡單,方便,高效的Go語言的遊戲伺服器底層. 最終使用這些工具及庫編寫整個遊戲伺服器框架, 我的感受是很不錯的

細節看來, 有如下的幾個點:

語言, 庫
Golang語言特性和C很像, 簡單, 一張A4紙就能寫完所有特性. 你想想看, C++到了領悟階段, 也只用那幾個簡單特性, 剩下的都是一大堆解決各種內存問題的技巧. 而Golang一開始就簡單, 何必浪費生命去研究那一大堆的奇技淫巧呢?

Golang的坑只有2個:1. interface{}和nil配合使用, 2. for循環時, 將循環變數引入閉包(Golang, Lua, C#閉包變數捕獲差異) 完全不影響正常使用, 複合語言概念, 只是看官方後面怎麼有效的避免

用Golang就忘記繼承那套東西, 用組合+介面

用Golang伺服器如何保證解決遊戲伺服器存檔一致性問題? stop the world是肯定的, 但是Golang可以從語言層並發序列化玩家數據, 再通過後台存檔

channel是goroutine雖然是Golang的語言特性. 但是在編寫伺服器時, 其實只有底層用的比較多.

Golang的第三方庫簡直多如牛毛, 好的也很多

不要說模板了, C#的也不好用, 官方在糾結也不要加, 使用中, 沒模板確實有點不方便. 用interface{}/反射做泛型對於Golang這種強類型語言來說,還是有點打臉


運行期
Golang和C++比性能的話, 這是C++的優勢, Golang因為沒虛擬機, 只有薄薄的一層調度層. 因此性能是非常高的, 用一點性能犧牲換開發效率, 妥妥的

1.6版後的GC優化的已經很好了, 如果你不是高性能,高並發Web應用, 非要找出一堆的優化技巧的話. 只用Golang寫點遊戲伺服器, 那點GC損耗可以忽略不計

和其他現代語言一樣, 崩潰捕捉是標配功能, 我用Golang的伺服器線上跑, 基本沒碰到過崩潰情況

熱更新: 官方已經有plugin系統的提交, 跨平台的. 估計很快就可以告別手動cgo做so熱更新

開發, 調試, 部署, 優化
LiteIDE是我首選的Golang的IDE, 雖然有童鞋說B格不高. 但這估計實在是找不到缺點說了, 別跟我說Visual Studio, 那是宇宙級的...

曾經聽說有人不看好Golang, 我問為啥: 說這麼新的語言, 不好招人,後面打聽到他是個策劃... 好吧
真實情況是這樣的: Golang對於有點編程基礎的新人來說, 1周左右可以開始貢獻代碼. 老司機2~3天.

開發效率還是不錯的, 一般大的遊戲功能, 2*2人一周3~4個整完. 這換C++時代, 大概也就1~2個還寫不完. 對接伺服器sdk的話, 大概1天接個10多個沒問題

Golang自帶性能調優工具, 從內存, CPU, 阻塞點等幾個方面直接出圖進行分析, 非常直觀, 可以參考我博客幾年前的分析: 使用Golang進行性能分析(Profiling)

Golang支持交叉編譯, 跨平台部署, 什麼概念? linux是吧? 不問你什麼版本, 直接windows上編譯輸出一個elf, 甩到伺服器上開跑.不超過1分鐘時間..

現在北上廣深蓉很多新開項目都選擇了Golang,就是看到Golang的開發效率和招人上面
對於Golang開發還有糾結可以看下我的博文:伺服器開發語言比較

打個廣告, 各種開發筆記, 參考 戰魂小築 - C++博客

開源伺服器網路庫, https://github.com/davyxu/cellnet 歡迎賞星

多個商用項目使用的 GitHub - davyxu/tabtoy: 跨平台的高性能便捷電子表格導出器


我們公司正在用Go開發頁游。上線運行有一段時間了,效果還算滿意。

用Go開發大型mmorpg服務端不會有問題的,如果掉坑裡肯定不會是語言的問題。

唯一比較可能掉進去的坑就只有GC,其實很容易預防和調整的,具體細節可以看我博客分享的文章。

但是技術選型不只是選語言,如果當時我手頭有一套性能滿意,開發效率OK,人員補給不會有問題的技術方案,不管是什麼語言的,我肯定不會放棄它而選擇冒險的。

我去年項目立項時選擇Go是有以下一些考慮的:

1. 前一個項目用Erlang開發的,活動時間一到,密集運算CPU就受不了,這點很不滿意
2. 項目過程中出現過補人難的情況,聽過Erlang並願意轉Erlang的人少,招來了培訓到加入開發又要一段時間
3. 因為前兩點,所以新項目想找一個解決性能問題又解決人員問題的技術方案
4. 我自身沒有C/C++項目經驗,只會點皮毛語法,短時間要上手並拿出可用的框架不現實
5. C/C++開發人員我們這也不好招
6. 那會正好Go 1.0即將發布,我估摸著項目上線後Go還會更完善,有點賭一把的意思
7. 我給自己設想的最壞情況是Go不行的時候可以用CGO補救,當時考慮比較多的是性能,但實際上性能沒問題,倒是用CGO做了GC優化,補救了自己最初設計上的不合理。
8. Go的語法元素非常之少,並且是類C的命令式語音,又有Google這個開發人員心中形象完美的親爹,人員補充上應該比Erlang容易

對了,我最近做了個Go語言的V8引擎綁定,可以用來做遊戲邏輯腳步啥的。歡迎各路勇士踴躍跳坑:http://github.com/idada/go-v8


因為我自己本身不是做mmorpg的,這裡只是給出我認識的一些人給我的反饋信息。
1. 我認識的幾個人都有用在遊戲開發中,手游、頁游都有,所以不能說沒有成功案例
2. golang主要存在的問題是GC問題,但是如果你的應用訪問量沒有上千萬的話,達達分享的如何有效的控制GC非常寶貴的經驗,而且下一版本Go1.3基本上能夠解決Go的GC問題。
3. golang的並發控制是最大的特點,能夠很容易就實現高並發
4. 目前golang發布的節奏是每半年一個版本,而且基本都是性能的提升,就目前的性能而言,你的應用已經足夠用了。
5. 開發工具LiteIDE寫代碼就非常棒,寫Go代碼足夠足夠了
6. Go方面的資料現在還是挺多的吧,而且你遇到問題去golang-nuts去問,都會很快得到答覆
7. 而且對於Go在Google內部使用的情況來看,網路這一塊的包是非常穩定和可靠的,用來開發遊戲很合適啊


想必到今天,用 Golang 開發大型 MMORPG 遊戲伺服器的應該案例鮮見。但在手游和頁游上,Golang 到挺活躍的。我是 C++ 轉 Golang,說說感受。

  1. 執行效率。Golang 是編譯型的,給人的感覺是性能可靠。
  2. 開發效率。Golang 提供了豐富的反射支持,用在框架開發上真是得心應手,甩開 C++ 幾條街。由於較好的反射支持,能夠寫出更加簡潔和易用的介面,對於上層開發效率有比較明顯的推動作用。再說,Golang 語言本身很簡單,不但是入門成本低,開發中需要考慮的語言本身的問題也少。
  3. 不崩潰。因為所有錯誤都可以捕獲,所以只要不出現把內存耗盡、死循環等致命問題,大多數情況,在一個精心設計的框架下,伺服器穩定性能夠有很大的保障。
  4. Goroutine + 同步阻塞。此模式能夠解決 C++ 伺服器中存在的極少的複雜的非同步調用的問題。
  5. 對人的要求低。C++ 對開發人員素質要求過高。相同素質的人,用 Golang 能寫出很漂亮的東西。

Golang 本身是有那麼一點「特殊」的語言,沒有經過細緻的思考(包括業務的思考,語言本身的思考),Golang 寫不出好框架,甚至讓你掉坑。


xingo golang分散式遊戲伺服器開發框架,支持快速搭建分散式架構的遊戲伺服器,xingo伺服器承載上線只跟遊戲具體邏輯有關,支持橫向擴展。使用go語言開發兼具開發效率和性能兩大優勢github地址:viphxin/xingo 自帶mmo遊戲的demo,地址:viphxin/xingo_demo - 碼雲 - 開源中國


大型 MMORPG 遊戲服務端,估計以後都很難看到golang的「成功案例」。障礙不在於GC這些,而在於現在大型 MMORPG 只有大公司能搞得動。而大公司一般都已經有大牛,已經有積累了n年的服務端c/c++框架。

如過真的有新進入者,需要從頭開發服務端框架,那用go幾乎是最佳選擇。

對頁游/手游來說,go可以說是天地廣闊,大有可為。一個用C++半年抄出一個遊戲且時不時會宕機再加3個月才能搞穩定的團隊 VS 一個用go三個月抄出一個遊戲且從不宕機的團隊,嘿嘿......


看完答案後,糾正一些常見錯誤,曲線救國回答一下題主;

1.為什麼golang的開發效率高?

golang是一編譯型強類型語言,它在開發上的高效率主要來自於後發優勢,不用考慮舊有噁心的歷史,又有一個較高的工程視角。良好的避免了程序員因為「 { 需不需要獨佔一行 」這種革命問題打架,也解決了一部分趁編譯時間找產品妹妹搭訕的階級敵人。

  • 它有自己的包管理機制,工具鏈成熟,從開發、調試到發布都很簡單方便;
  • 有反向介面、defer、coroutine等大量的syntactic sugar;
  • 編譯速度快,因為是強類型語言又有gc,只要通過編譯,非業務毛病就很少了;

它在語法級別上支持了goroutine,這是大家說到最多的內容,這裡重點提一下。首先,coroutine並不稀罕,語言並不能超越硬體、操作系統實現神乎其神的功能。golang可以做到事情,其他語言也可以做到,譬如c++,在boost庫裡面自己就有的coroutine實現(當然用起來跟其他boost庫一樣噁心)。golang做的事情,是把這一套東西的使用過程簡化了,並且提供了一套channel的通信模式,使得程序員可以忽略諸如死鎖等問題。

goroutine的目的是描述並發編程模型。並發與並行不同,它並不需要多核的硬體支持,它不是一種物理運行狀態,而是一種程序邏輯流程。它的主要目的不是利用多核提高運行效率,而是提供一種更容易理解、不容易出錯的語言來描述問題。

實際上golang默認就是運行在單OS進程上面的,通過指定環境變數GOMAXPROCS才能轉身跑在多OS進程上面。有人提到了網易的pomelo,開源本來是一件很不錯的事情,但是基於自己對callback hell的偏見,我一直持有這種態度:敢用nodejs寫大規模遊戲伺服器的人,都是真正的勇士 : ) 。

2、Erlang與Golang的coroutine有啥區別,coroutine是啥?

coroutine本質上是語言開發者自己實現的、處於user space內的線程,無論是erlang、還是golang都是這樣。需要解決沒有時鐘中斷;碰著阻塞式io,整個進程都會被操作系統主動掛起;需要自己擁有調度控制能力(放在並行環境下面還是挺麻煩的一件事)等等問題。那為啥要廢老大的勁自己做一套線程放user space裡面呢?

  1. 並發是伺服器語言必須要解決的問題;
  2. system space的進程還有線程調度都太慢了、佔用的空間也太大了。

把線程放到user space的可以避免了陷入system call進行上下文切換以及高速緩衝更新,線程本身以及切換等操作可以做得非常的輕量。這也就是golang這類語言反覆提及的超高並發能力,分分鐘給你開上幾千個線程不費力。

不同的是,golang的並發調度在i/o等易發阻塞的時候才會發生,一般是內封在庫函數內;erlang則更誇張,對每個coroutine維持一個計數器,常用語句都會導致這個計數器進行reduction,一旦到點,立即切換調度函數。

中斷介入程度的不同,導致erlang看上去擁有了preemptive scheduling的能力,而golang則是cooperative shceduling的。golang一旦寫出純計算死循環,進程內所有會話必死無疑;要有大計算量少io的函數還得自己主動叫runtime.Sched()來進行調度切換。

3、golang的運行效率怎麼樣?

我是相當反感所謂的pingpong式benchmark,運行效率需要放到具體的工作環境下面考慮。

首先,它再快也是快不過c的,畢竟底下做了那麼多工作,又有調度,又有gc什麼的。那為什麼在那些benchmark裡面,golang、nodejs、erlang的響應效率看上去那麼優秀呢,響應快,並發強?並發能力強的原因上面已經提到了,響應快是因為大量非阻塞式io操作出現的原因。這一點c也可以做到,並且能力更強,但是得多寫不少優質代碼。

然後,針對遊戲伺服器這種高實時性的運行環境,GC所造成的跳幀問題確實比較麻煩,前面的大神 @達達 有比較詳細的論述和緩解方案,就不累述了 。隨著golang的持續開發,相信應該會有非常大的改進。一是屏蔽內存操作是現代語言的大勢所趨,它肯定是需要被實現的;二是GC演算法已經相當的成熟,效率勉勉強強過得去;三是可以通過incremental的操作來均攤cpu消耗。

用這一點點效率損失換取一個更高的生產能力是不是值得呢?我覺得是值得的,硬體已經很便宜了,人生苦短,讓自己的生活更輕鬆一點吧: )。

4、基於以上的論述,我認為採用go進行小範圍的MMORPG開發是可行的。


很多時候回答這類問題大家喜歡用一種特徵列舉的方式,比如:C有什麼什麼特徵,所以適合,Go有什麼什麼特徵所以不適合。但其實對於實際想獲得答案的人這種特徵列舉並沒有想的那麼有用,因為你沒法判定那個片面那個不片面,那些是偏見,那些是純主觀。所以最簡單實用的方法是去確認什麼是被證明過的成熟的技術,比如有多少成功的mmorpg用的是這門語言或框架,另一個是看那個社區成熟。畢竟大多時候事業本身並不適合為新技術背書。


如果跟C語言比,大部分腳本都勝出啊。Go, Node.js, Python ......
網易弄過一個Node.js的開源伺服器框架。
至於IDE, 不重要,做伺服器開發很少會要開著IDE調試的。最常用的手段就是打Log. 設置了斷點也很難調,多個客戶端並發。
那種單客戶端連接進來就可以重現的bug倒是可以用IDE調,但是這種bug本來就容易解決。
用腳本語言,有一個很大的好處是容易做自動測試,可以更好地保證代碼質量。
--------------------------
開發效率當然是腳本高。運行效率,其實更重要的是並發,框架合理的話增加機器就可以直接提高效率增加人數。


我的看法是:
未來肯定會成為標配,也就是 mmorpg 最為廣泛接受的方案。

至於:
1. 你信不信
2. 你應該什麼時候介入

這個別人幫不了你。


可以,但我現在了解到的大部分webgame大多採用c c++ c# 做底層 python lua js做腳本,直接用c c++ c#(scut開源) python(firefly開源) js(node)(網易開源) go(達達,仙俠道,貌似有用js做腳本) erlang的也有,但技術選型其實是考慮人員配置和團隊成長,不必糾結,而且大部分情況是沒得選。
補充:
剛剛又看到 雲風的c+lua框架cloudwu/skynet 路 GitHub 大家可以入門也可以直接用。

雲風skynet服務端框架研究 這個是我目前研究和收集的內容。


這個是基於你對 MMORPG 的認知的。

以上的回答幾乎都是「可以,首選,未來的標配」,但幾乎都沒有意識到他們再用或者即將用到的地方是「手游,頁游」,亦或是小型morpg遊戲

對於手游,頁游或者規模不太大的項目,用 GO 無疑是最好的選擇,至於原因,上面一大堆答案。
不過針對大型項目,選擇 C/C++ 在今後很長時間內,都不會改變

我想過把以前做的頁游手游伺服器用 GO 來開發,都會更好,不過如果用 GO 去做一款 WOW 這樣的遊戲伺服器,我仍然覺得會很坑,當然,這也可能受限於我自己的水平了


某居的 某俠世界 後端用 Golang開發的, 開服時的卡頓 掉線問題頻發,
做複雜度較高的AOE廣播量極其頻繁 的MMO時還是謹慎一點吧。
一般的卡牌類 回合類 用自己最熟悉 最喜歡的就行。

----------------------------

ps:補充一下,X人公司的 火爆輕對戰手游 山寨 http://agar.io 的 某球大作戰,
後端也是用 Go 語言開發的,適合小團隊快速作戰試錯,並且具備不錯的擴展能力。


下面是我在準備寫一個新的游服時技術選型的比較,最後我選了C#;
C#的優點:
1.有強大IDE,無論編寫還是調試都非常容易,可以節省大量時間。
2.有大量資料可查
3.不會有Runtime層的內存泄漏。
4.有成功先例,說明用起來沒問題。
5.運行速度快。
6.我非常熟悉。
7.代碼框架可以參考傳統遊戲伺服器的實現方式。

缺點:
1. 相對go,布署比較麻煩。
2. linux上得用mono,性能有下降。
3. 非開源(相對GO,其實從實用角度來說,不是什麼問題)。

golang的優點:
1.原生高並發
2.布署方便

golang的缺點
1.沒有強大的IDE,開發和調試都不方便(至少是沒有用VS那麼方便)
2.沒有大量資料。
3.有runtime內存泄漏問題。
4.市面上沒聽說過有golang開發的遊戲伺服器,沒先例,無人研證過可不可用,有風險。
5.運行速度並不比c#有優勢。
6.我沒c#那麼熟悉
7.代碼框架雖然也可以參考傳統遊戲伺服器的實現方式,但這樣就失去了高並發和go程的優勢,所以這塊勢必要重新思考,增加了風險。


技術選型階段,不知道該用c+,java or golang。看了很多技術文章,說法很多,各不相同,大多是某一門派的自吹自擂型文章,一點沒有參考性。於是決定自己寫例子
用c+,java,golang分別寫了測試程序,模擬幾千個客戶端發送請求,服務端進行大數組排序,然後傳遞排序結果給伺服器,得出結論如下。
速度上,c+和golang1.6一樣快,java速度比前兩位略慢,大約慢10%左右,還能接受,從速度上來說三者差不多,考慮到招人成本,java勝出。
如果在遊戲開發中,假設一個用戶在服務端的數據有2m,那麼2000個用戶就需要4G內存,真正的問題是內存問題。在4G物理內存的主機上測試,打開swap分區,這3個程序才能正常運行,否則oom。其中,java和golang的內存佔用居高不下,不知道gc去哪裡了,golang的gc尤其不給力,很快內存暴漲到上限被系統kill,java再多處理一些連接後也被系統kill了,只有c++,及時釋放內存。
我仔細想了一下,為什麼java大量用於web,而很少用於遊戲呢,看來關鍵就是內存問題。對於web應用來說,大多數情況下讀多寫少,一個用戶的數據多的也不過幾kb,而遊戲則不同,讀少寫多,一個用戶的數據量多的能有幾mb,對內存的需求,遊戲可能是web的1000倍。如果使用java開發web應用,gc不釋放內存也沒問題,反正就是幾k而已,但是開發遊戲java就力不從心了。
總結一下,這三門靜態編譯語言,運行速度其實是差不多的。學習難度上,c+&>java&>golang,golang真心簡單,我連學語法帶寫測試程序,2天就寫出了測試用的客戶端和伺服器。不過golang的gc問題。還是看大家用來幹什麼吧,web還是用java,遊戲java或c+,golang嘛,對我來說,還是要保守的再觀察一下1.7版本。


優勢。開發效率高。

劣勢 速度相對慢。但對於一般網遊來說,應該可以忽略。

個人感覺開發效率對大部分團隊來說是首要的,因為你能快速出產品比什麼都強。
伺服器效率go比不上c++,但是對大部分人來說肯定也夠了。

go另外一個劣勢就是對大多數程序員來說是一門新語言,需要學習。不像c,java拿來就寫。
不過這一點可以被開發效率高彌補。


從趨勢上看,go以後發展最多的肯定是後端的應用,gc的問題只是暫時的,c++被取代是毫無疑問的。


不建議用xxlang,用腳本,比如lua
只提一個工程問題,遊戲開發中,很多邏輯前後端公用,怎麼處理?
別告訴我前端要加個xxlang的編譯器。
如果你告訴我,需要再xx一次,當我沒說。


推薦閱讀:

《最終幻想14》遊戲體驗如何?有哪些特色?
你的第一隻神奇寶貝會選誰33%的人選傑尼龜 55% 的人選小火龍18% 的人選妙蛙種子 。什麼心理?
真的可以通過數學方法提高賭博中贏的幾率嗎?
穿越火線(CF)這款遊戲有多賺錢?它能成功的原因在哪裡?
如何玩好《天天愛消除》這個遊戲?

TAG:遊戲 | MMORPG | 遊戲伺服器 | Socket | Go 語言 |