1. 程式人生 > >H5十人牛牛架設遊戲服務器架構: 內核設計

H5十人牛牛架設遊戲服務器架構: 內核設計

tar 能夠 isoc 當前 定義 str 情況 image start

H5十人牛牛架設遊戲服務器查看(aqiulian.com),內核設計分析Q_212303635;接下來講解一下內核模塊分析。內核的幾個組件被設計成Service,也就是說這幾個模塊都要實現如下接口:

技術分享圖片

圖1 IService接口

Start方法用來啟動服務。

Stop 方法用來關閉服務。

IsService 方法用於查詢當前服務是否正在工作。

內核中的幾個Service都不能夠直接創建,Applications在使用這些Service的時候首先要得到一個IServiceMgr的實例,這被實現成了一個另類地單例模式。IServiceMgr的接口定義如下:

技術分享圖片

圖2 IServiceMgr接口

IServiceMgr提供兩類接口:

1) 獲取Service的接口,這樣直接得到具體的Service,是因為內核的Service比較固定。沒有必要用GetService(strServiceName)這種方法。

GetAsyncService 返回AsyncService的實例

GetDBService 返回DatabaseService的實例

GetTCPService 返回TCPServerService的實例

GetTimerService 返回定時器實例

2) 一個靜態的單例方法Instance。它申明在接口層,但是需要在IServiceMgr的實現中去實現它。它返回IServiceMgr的實例。

由於IServiceMgr的實現只是簡單地將IAttemptService,ITCPServerServer, IDatabaseService,ITimerService的實現組合在了一起,所以它的實現不會詳細描述。

1 AsyncService詳細設計

技術分享圖片

圖3 AsyncService的詳細設計

AsyncService主要是提供給其他3個Service使用的,它實現了IService接口和IAsyncService接口。因為與異步相關的功能基本上都被boost::asio實現,所以AsyncService主要只是管理boost::asio的實例 。IAsyncService只提供了一個方法:

GetIOService 返回一個可用的boost::asio::io_service的實例

AsyncService組合了boost::asio和ThreadPool,其中boost::asio::io_service的數目和機器的cpu總數相同,而ThreadPool中線程總數為2倍的cpu數。所有ThreadPool中的線程都將作為工作線程,它們的入口函數都是io_service::run。

2 TimerService詳細設計

技術分享圖片

圖4 TimerService的結構圖

TimerService實現了IService和ITimerService接口。ITimerService提供如下接口:

1) SetTimer(timerId,milisecs,timerFunc,repeatTimes) 設置一個id為timerId的定時器,這個定時器會被激

發repeatTimes次,每兩次被小激發的時間間隔為millsecs毫秒。每次被激發都會調用 timerFunc這個函數。

2) KillTimer(timerId) 取消id為timerId的定時器。

3) KillAllTimer() 取消所有的定時器,一般用在系統關閉時調用。

TimerService管理著一些TimerItem,Applications層用一個新的timerId,調用SetTimer時,TimerService就會創建一個新的TimerItem, 而在調用KillTimer時,就會銷毀掉與其相關的那個TimerItem。TimerService的實現依賴與AsyncService,因為定時器本質上也是異步操作。將由AsyncService中的io_service來統一調度。

需要註意以下幾點:

1) 傳給SetTimer的timerFunc這個函數要是線程安全的,因為不確定會在哪個工作線程的context中調用它,同時如果你的好幾個定時器公用同一個timerFunc, 就可能對共享資源造成競爭。

2) SetTimer進如果發現已經存在相同id的TimerItem, 不會創建一個新的TimerItem,而是取消先前的定時器。修改其參數後啟動。

3 TCPServerService詳細設計

技術分享圖片

圖5 TCPServerService結構圖

TCPServerService實現了IService接口和ITCPServerService接口。ITCPServerService的幾個主要接口說明:

1) SendData 通過指定的ISocketItem發送數據, 數據在一般情況下由4個參數: MainCmd, SubCmd, Data, DataSize (可以參與總休設計中關於協議的部分的描述) 。有的時候Data為空,就不需要Data和DataSize這兩個參數了。

2) SendDataBatch 給所有連接發送數據。這是批量發送的,所有連接池中對應的客戶端都會收到。

3) CloseSocket 關閉指定的連接。

4) SetObserver 設置監聽者。用以接收異步通知。

TCPServerService 管理著一個客戶端來的連接池。這個連接池由SocketItem組成,每一個SocketItem都與一個整數標識對應,Applications使用這個標識來發送數據和接收數據。SocketItem主要提供下面幾個接口:

1) GetIndex 獲取與其對應的唯一標識

2) GetRound 由於每個SocketItem都是可以重用的,所以為了防止混亂,比如說一個SocketItem在前一時刻對應著client1, 但是現在對應著client2。client1曾經的一個請求現在才要返回,這時如果沒有GetRound就會把client1的處理結果錯誤地返回給client2。從這裏也可以看出,每個SocketItem的round是在連接建立的時候會增加。

3) IsConnected 是否處於連接狀態。

4) SendData 發送數據。

5) GetClientAddress 得到客戶端的IP地址

6) GetConnectTimer 獲取連接時間。

7) Close 關閉連接。

也許你會問了,我怎麽只看到發送數據的接口,而沒有接收數據的接口呢?因為這是個異步架構,在有連接到來,或者數據到來的時候,你會收到通知的。前提條件是你調用SetObserver設置了監聽者。TCPServerService的監聽都需要實現ITCPServiceObserver接口, TCPServerService通過這個接口提供的方法來通知你連接和讀取事件:

1) OnSocketAccept 在新連接到達時,會調用你這裏面的內容。

2) OnSocketRead 在數據讀取完成後,會調用你提供的這個方法做進一步處理。

3) OnSocketClose 告訴你連接將要關閉。

需要註意的是如果你這三個方法中有共享的數據,要加鎖保護。因為工作線程可能會產生競爭狀態。

和TimerService一樣,TCPServerService的異步調度依賴於IAsyncService。

4 DatabaseService詳細設計

技術分享圖片

圖6 DatabaseService結構圖

可以對比一下DatabaseService和TCPServerService的結構圖,你會發現他們是那麽地相似。對的,它們的設計思路如出一轍。DatabaseService實現了IService和IDatabaseService這兩個接口。IDatabaseService主要只提供了3個接口:

1) Connect 連接到一個數據庫

2) Query 進行查詢。 這裏有兩點要註意:1) Query以後不會立馬得到結果,因為這是異步的; 2) 存儲過程的調用也得使用這個方法,你只要將query語句寫成 ‘select stroage_procedure(param1,param2,...)‘ 就行了。

3) SetObserver 設置觀察者。因為查詢是異步的,所以你要設一個觀察者來得到通知。

DatabaseService管理著一些數據庫連接DBConnect, 每一個DBConnect也與一個整數標識相關聯,可以通過GetIndex獲得。同時你可以通過IsConnect來查詢這個DBConnect是否處於連接狀態。

在實現IDBServiceObserver時,你需要實現下面兩個方法:

1) OnDBConnect 在數據庫連接建立時會調用

2) OnQueryEnd 在這裏你可以得到一個表示查詢結果的QueryResult對象。你可以通過它知道查詢的狀態,以及結果信息。

H5十人牛牛架設遊戲服務器架構: 內核設計