Figure.1

3. 軟件架構(gòu)

HS是被設(shè)計成通用性模塊,理論上可以供所有應(yīng)用服務(wù)器接入使用,如Figure.2所示:

Figure.2

由于HS模塊自身并沒有網(wǎng)絡(luò)傳輸功能,在集成中還需要將應(yīng)用服務(wù)器的網(wǎng)絡(luò)I/O接口接入到HS模塊(常規(guī)情況下,應(yīng)用服務(wù)器的網(wǎng)絡(luò)I/O模塊都會提供單獨接口?)。

整體架構(gòu)如Figure.3,HS自己運(yùn)行一個線程,對所有異步傳遞到HS模塊的數(shù)據(jù),先使用queue進(jìn)行排隊緩存,再在本線程內(nèi)一次性將其傳輸?shù)脚渲玫腟lave端,同時這部分?jǐn)?shù)據(jù)也會寫入模塊的第三方存儲(HS目前只實現(xiàn)了Memory存儲)。

Slave在接收到Master傳輸?shù)膁ata后,更新應(yīng)用服務(wù)器相關(guān)內(nèi)存(根據(jù)Master發(fā)送的KEY可以確定具體的內(nèi)存類型),同時也會將接收到的數(shù)據(jù)寫入自身的數(shù)據(jù)緩沖隊列和第三方存儲。

Master和Slave只要編寫很少代碼(發(fā)送時HOOK,接收時更新)就可以實現(xiàn)一個完備的hot-standby server。

Figure.3

這里就有個疑問了,為什么Slave也需要維護(hù)一個queue和第三方存儲呢?這是因為Slave可能會在未來的某一天會變成Master,需要同步數(shù)據(jù)給未來的一個Slave。Figure.4流程圖說明了服務(wù)器啟動的過程。

Figure.4

4. 模塊化

HS可以單獨編譯成動態(tài)庫形式(.so)使用。

具體實現(xiàn)中使用boost的一些庫,主要有io_service,thread,bind,shared_ptr等。

不過在編譯時可以選擇將boost庫靜態(tài)編譯,實際使用上就不用單獨進(jìn)行依賴了。

需要說明的是,為了更好的支持HS的運(yùn)行,遠(yuǎn)程過程調(diào)用模塊被開發(fā)出來,這里就不詳述了。

5. 網(wǎng)絡(luò)傳輸如何處理突如其來的大數(shù)據(jù)量

在某種極端情況下,當(dāng)Master啟動了很久之后,Slave才姍姍來遲,Master可能積累了大量的數(shù)據(jù)(超過4G),這個時候如果Master對Slave進(jìn)行無限制的傳輸數(shù)據(jù),會占用大量的網(wǎng)卡資源(不過一般雙網(wǎng)卡,不影響外網(wǎng)服務(wù)),最重要的會占用大量網(wǎng)絡(luò)線程資源(HS和應(yīng)用服務(wù)器公用網(wǎng)絡(luò)線程)。

實際測試中發(fā)現(xiàn),由于4G的小塊數(shù)據(jù)大小不一,傳輸耗時超過1分鐘。為了避免對應(yīng)用服務(wù)器的網(wǎng)絡(luò)線程擁塞,加入了傳輸數(shù)據(jù)的流量控制,在每個間隔時間內(nèi)只傳輸指定配置的數(shù)據(jù)量,測試證明,這個方法解決了所有相關(guān)問題。

第三方存儲有什么用?

Slave端斷開后或者在Master啟動一段時間后再連上來時,用于存儲歷史備份數(shù)據(jù)。就是說Slave 在斷開很長時間之后再連上來,期間所有的歷史數(shù)據(jù)都是在第三方存儲中。連上后,首先需要同步的第三方存儲的數(shù)據(jù),完成后再對queue中的數(shù)據(jù)進(jìn)行實時同步。

6. Socket的幽靈屬性keepalive

為了檢測網(wǎng)線斷開或者不可知的網(wǎng)絡(luò)異常,HS需要一套能夠檢測網(wǎng)絡(luò)真斷開,還是偽斷開(比如網(wǎng)絡(luò)短時間內(nèi)的不通),首先想到了利用TCP/IP協(xié)議自身的屬性,即KEEPALIVE,經(jīng)使用測試發(fā)現(xiàn),這個不是很好的檢查機(jī)制,至少不是我們需要的。因為KEEPALIVE依賴系統(tǒng)的三個屬性,如下所示:

系統(tǒng)設(shè)置

# cat /proc/sys/net/ipv4/tcp_keepalive_time

7200

# cat /proc/sys/net/ipv4/tcp_keepalive_intvl

75

# cat /proc/sys/net/ipv4/tcp_keepalive_probes

9

簡單說明下,這個三個屬性表示TCP/IP協(xié)議層會在7200秒沒有收到客戶端消息的情況下,發(fā)送10(9+1)個報文段,每兩個間隔75秒,若客戶端對這些信息都沒有響應(yīng),則終止該連接。

不使用這個屬性的兩個理由,一是這些信息屬于系統(tǒng)屬性級別的改動,二是實際測試中發(fā)現(xiàn)很不穩(wěn)定。

以下為設(shè)置keepalive的代碼:

int optval = 1;

socketlen_t optlen = sizeof(optval);

setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);

更有效的心跳方案:

就是自己實現(xiàn),方案比較土,簡單描述下:

服務(wù)器維護(hù)兩個變量A和B,一個定時器,客戶端每來一個請求包,A變量自增1,同時在定時器到點時,檢測A和B是否相同,如果不同表明客戶端是活動的,同時將A同步到B,開始下一輪定時器。若一個連接有N次的定時器到點是都未活動,則判定客戶端斷開,關(guān)閉該連接。

7. OVER

【編者加注】

專注于社交游戲的研發(fā)與運(yùn)營,逐漸對社交游戲產(chǎn)品的業(yè)務(wù)越來越熟悉,不斷地總結(jié)與分析,加快社交游戲產(chǎn)品的研發(fā)速度,我們技術(shù)團(tuán)隊做很多研究與嘗試,為此我們開發(fā)出來產(chǎn)品:

1) 數(shù)據(jù)中間件:解決大用戶并發(fā)與大數(shù)據(jù)量的問題,不需要游戲研發(fā)工程師關(guān)心數(shù)據(jù)的存取等;

2) 任務(wù)服務(wù)器:解決游戲產(chǎn)品眾多活動或獎勵活動的舉辦,以及游戲自身任務(wù)的配置與管理;

3) 統(tǒng)計服務(wù)器:我們玩家的操作日志數(shù)據(jù)量太大,無法全部存儲到服務(wù)器上,為此有選擇地存儲相關(guān)玩家的行為日志數(shù)據(jù),并且完成數(shù)據(jù)分析的工作;

4) 好友列表服務(wù)器:社交游戲產(chǎn)品主要是接入眾多的社交網(wǎng)站平臺,為此要實現(xiàn)一套通用的好友列表服務(wù)器;

5) …..等其他游戲引擎組建

隨著推出上述相關(guān)通用性游戲引擎的組建,我們也逐漸贏得更多時間與精力可以做更有意義的事情,比如我們可以靜下心研究解決這些服務(wù)器作為單點運(yùn)行的問題,為此研發(fā)出解決各個游戲引擎組建服務(wù)的主備提供服務(wù)的通用性組建,也即其他游戲引擎組建通過引入hot-standby組建,可以解決單點故障的問題。這個通用性組建,也可以為非社交游戲行業(yè)的服務(wù)器后臺程序的熱備模式,提供一定的技術(shù)參考價值。感謝@ZEROV17的投稿支持,也歡迎各位技術(shù)朋友站內(nèi)留言或者新浪微博直接交流,同時也非常感謝零度視角F為此項目所作的貢獻(xiàn)!

分享到

tangrong

相關(guān)推薦