為什麼go語言適合開發網遊伺服器端
阿新 • • 發佈:2019-02-13
個人覺得golang十分適合進行網遊伺服器端開發,寫下這篇文章總結一下。 從網遊的角度看: 要成功的運營一款網遊,很大程度上依賴於玩家自發形成的社群。只有玩家自發形成一個穩定的生態系統,遊戲才能持續下去,避免鬼城的出現。而這就需要多次大量匯入使用者,在同時線上使用者量達到某個臨界點的時候,才有可能完成。因此,多人同時線上十分有必要。 再來看網遊的常見玩法,除了排行榜這類統計和資料彙總的功能外,基本沒有需要大量CPU時間的應用。以前的專案裡,即時戰鬥產生的各種傷害計算對CPU的消耗也不大。玩家要完成一次操作,需要通過客戶端-伺服器端-客戶端這樣一個來回,為了獲得高響應速度,滿足玩家體驗,伺服器端的處理也不能佔用太多時間。所以,每次請求對應的CPU佔用是比較小的。 網遊的IO主要分兩個方面,一個是網路IO,一個是磁碟IO。網路IO方面,可以分成美術資源的IO和遊戲邏輯指令的IO,這裡主要分析遊戲邏輯的IO。遊戲邏輯的IO跟CPU佔用的情況相似,每次請求的位元組數很小,但由於多人同時線上,因此併發數相當高。另外,地圖資訊的廣播也會帶來比較頻繁的網路通訊。磁碟IO方面,主要是遊戲資料的儲存。採用不同的資料庫,會有比較大的區別。以前的專案裡,就經歷了從MySQL轉向MongoDB這種記憶體資料庫的過程,磁碟IO不再是瓶頸。總體來說,還是用記憶體做一級緩衝,避免大量小資料塊讀寫的方案。 針對網遊的這些特點,golang的語言特性十分適合開發遊戲伺服器端。 首先,go語言提供goroutine機制作為原生的併發機制。每個goroutine所需的記憶體很少,實際應用中可以啟動大量的goroutine對併發連線進行響應。goroutine與gevent中的greenlet很相像,遇到IO阻塞的時候,排程器就會自動切換到另一個goroutine執行,保證CPU不會因為IO而發生等待。而goroutine與gevent相比,沒有了python底層的GIL限制,就不需要利用多程序來榨取多核機器的效能了。通過設定最大執行緒數,可以控制go所啟動的執行緒,每個執行緒執行一個goroutine,讓CPU滿負載執行。 同時,go語言為goroutine提供了獨到的通訊機制channel。channel發生讀寫的時候,也會掛起當前操作channel的goroutine,是一種同步阻塞通訊。這樣既達到了通訊的目的,又實現同步,用CSP模型的觀點看,併發模型就是通過一組程序和程序間的事件觸發解決任務的。雖然說,主流的程式語言之間,只要是圖靈完備的,他們就都能實現相同的功能。但go語言提供的這種協程間通訊機制,十分優雅地揭示了協程通訊的本質,避免了以往鎖的顯式使用帶給程式設計師的心理負擔,確是一大優勢。進行網遊開發的程式設計師,可以將遊戲邏輯按照單執行緒阻塞式的寫,不需要額外考慮執行緒排程的問題,以及執行緒間資料依賴的問題。因為,執行緒間的channel通訊,已經表達了執行緒間的資料依賴關係了,而go的排程器會給予妥善的處理。 另外,go語言提供的gc機制,以及對指標的保護式使用,可以大大減輕程式設計師的開發壓力,提高開發效率。 展望未來,我期待go語言社群能夠提供更多的goroutine間的隔離機制。個人十分推崇erlang社群的脆崩哲學,推動應用發生預期外行為時,儘早崩潰,再fork出新程序處理新的請求。對於協程機制,需要由程式設計師保證執行的函式不會發生死迴圈,導致執行緒卡死。