Nature Online 的技術

«Back

功能簡介

nature online(no)是以多人連線版本吃金幣的人為基礎所建立起來的一個網路架構實驗平台。

雛形版本功能如下:

新增功能如下:

Server架構

no底層是以smallworld2的Bigworld架構為基礎再往上架構出來的一個分散式game server架構,每一個server都是一個Bigword節點,設定好conf後Bigworld底層會自動建立並保持節點關係。底下是架構圖:

以上是no節點的大略介紹。

Server節點

每個server節點程式就是一個console程式,所以執行起來後在畫面上都以文字模式顯示狀態及訊息,同時也能以簡單的命令操作server功能。不知道server支援什麼指令時,只需輸入help即可得到簡單的指令列表及說明。

如圖所示的certer help列表可以看到,center有help,info,exit,shutdown,remote,fork等指令可使用。前3個指令help,info,exit是所有節點都支援的common指令,不同server節點可能會提供不同的特有指令,而shutdown,remote,fork是center特有的指令。server負載過大可用fork新增節點,要關機時用shutdown指令一次全部關機,就不必一個一個server關不遺漏。

雖然info是每個server都支援的指令,但根據server類型不同,顯示的info內容除了header格式相同外,其餘內容也會有不同。如上圖center的info就包含每一個連線到center的節點的info,而如下圖map的info內容就包含地圖info。

附帶提一下,center同時也內建web service,所以center的console內容和操作也可以透過browser對center作存取。

壓力測試

server程式開發最重要的就是穩定,想確保server穩定最簡單的方法是作該作的測試和夠多的測試。所以從一開始server雛形建立的同時,我也同時會建立一個testclient雛形。一開始也是一個console程式,後來再建立gui程式。

testclient的雛形就只是一個可以連線登入到game的console程式,可以顯示送到server和收到server的訊息內容這樣子就夠了,這樣簡單的程式就能讓整個server開發動起來,以後再以這樣的基礎繼續加功能繼續改良。最重要的是,有了testclient就能很方便快速的debug。

當server開發到一個程度後,想要開始作一點簡單的壓力測試時,可以很簡單的用batch file重複多開幾個testclient就行了。寫2個批次檔,RunTest1.bat一次執行一個testclient,RunTestN.bat可以透過RunTest1.bat用for迴圈一次執行多個testclient。

RunTest1.bat:

@echo off
title %1
test %1

RunTestN.bat:

@echo off
for /l %%i in (1,1,25) do start %~dp0RunTest1.bat %%i
for %%i in (11100 11101,11102) do start %~dp0RunTest1.bat %%i

這個方法很簡單很暴力,初期這樣作簡單的壓力測試還可以,中後期要作比較大量的壓力測試時就有問題了。因為每一個testclient執行一個console,100個testclient就100個console,電腦還勉強可以。但當開了200,300,400..到一個量之後電腦資源就被吃光不行了,所以後面勢必要改成一個testclient console可以支援多個連線才行,這樣就可以作更大規模的壓力測試。

除了可以大量產生client測試程式的batch外,有時候也需要多開指定server程式,所以又寫了一個簡單的batch可以開啟指定數量的不同server。

forkserver.bat:

@echo off
setlocal enabledelayedexpansion
echo PLEASE ENTER SERVER NAME? (ex:login)
set /p svr=
echo PLEASE ENTER HOW MANY SERVERS TO FORK? (ex:10)
set /p n=
echo PLEASE ENTER SERVER FIRST ID? (ex:1)
set /p first=
set /a last = %first% + %n% -1

for /l %%i in (%first%,1,%last%) do (
  cd %svr%
  start %svr% %%i
  cd ..
)

這個script詢問要開啟什麼類型server、數量以及server啟始ID。按下Enter鍵後,如下所示。

沒問題的話,就會同時開啟指定類型數量的server程式。

地圖同步機制

地圖物件的更新有二種類型,一是以當前位置狀態更新給client,如tree,bug,bird,base等。另一種是有起點和終點的長距離移動物件,如ship。第一種類型物件的更新資訊會不斷從server傳至client,讓client有機會可以更新畫面。第二種類型物件只有在需要的時候才更新給client,其餘時間由client自行根據移動物件的起止點作內插更新。

一開始為了簡化設計儘快可以進行後續開發和測試,client登入game後,每隔一段時間由game自動替這個client向map請求他的視野範圍內的可視物件狀態資訊。map回應視野內的物件資訊給game後,game再根據簡單的狀態檢查,只傳送client視野內有變化的物件資訊給client作畫面更新。

這是很簡單又暴力的方法,當client不多時還好,但當client多起來的時候server之間的封包量非常大而且重複性也非常高,server光是要處理這麼大量的封包就可能來不及消化,以致於來不及處理而堆積的封包愈來愈多server反應愈來愈慢。game這邊定時發給map的請求是暫時方便測試的作法,所以會有大量重複請求及大量多餘封包。以這樣的作法,在debug模式下同時開個200的client己經很吃力了。所以勢必需要改變作法,才能作更大量的壓力測試。

新的改良的方法的思路如下,地圖狀態的同步方向要由client->game->map逆轉,改成map->game->client。基本上就是要由map主動觸發狀態變化,而且只觸發一次,這樣立即把大量重複的通知消除。而由map觸發的通知傳送到所有game之後,再由這些game把這個狀態變化通知再傳送給所有應該看的到這個變化的所有client。因為這個方法的主要最大優勢是消除了非常大量的重複封包,所以在網路底層來不及處理的封包堆積問題基本上己經消失了,所以作壓力測試時很容易就能同時開啟成千上萬個client還很順暢。甚至debug模式開個1000,2000以上的client作簡單測試也沒問題。