快速構建MMO伺服器架構(七)高並發TCP網路架構

來源:互聯網
上載者:User

忙活了一個多星期,差不多把基於TCP的高並發串連網路架構測試穩定了。

目的:利用多線程把網路連接及資料包壓縮/解壓、加密/解密等等耗時的操作分流(asio對這些沒有原生的支援),順帶提供線程池架構。只對遊戲邏輯層暴露出單線程的外觀,隔離底層多線程的複雜度。

結構如(未遵循什麼標準,將就著看吧):

 

TCPSessionHandler:暴露給邏輯層的類,內部負責通過TCPIOThreadManager跟掛載於某個線程的TCPSession進行互動,對上層屏蔽多線程細節。聲明如下:class TCPSessionHandler : public std::enable_shared_from_this<TCPSessionHandler>,<br /> public boost::noncopyable {<br /> public:<br /> // ==================== TYPEDEFS =======================================<br /> // ==================== LIFECYCLE =======================================<br /> TCPSessionHandler();<br /> virtual ~TCPSessionHandler() {}<br /> // ==================== OPERATIONS =======================================<br /> // sends message to remote endpoint, the content of message would be consumed<br /> void SendMessage(NetMessage& message);<br /> // sends message to remote endpoint, the content of message would be consumed<br /> void SendMessage(NetMessage&& message);<br /> // closes the session<br /> void Close();<br /> // true if the session is closed.<br /> bool IsClosed() { return kInvalidTCPSessionID == session_id_; }<br /> // called when connection complete.<br /> virtual void OnConnect() = 0;<br /> // called when NetMessage received.<br /> virtual void OnMessage(const NetMessage& message) = 0;<br /> // called when TCPSession closed.<br /> virtual void OnClose() = 0;<br />};
 

(註:本文代碼風格盡量遵循 google c++ style guide
)

NetMessageList:NetMessage定義為邏輯上有明確分界的網路訊息,一個或多個NetMessage組成NetMessageList。

TCPIOThreadManager:管理一個或多個TCPIOThread,其中一個TCPIOThtread作為主線程邏輯運行。

CommandList:線程間互動的命令隊列,也是整個架構中唯一的線程間同步方式,稍候詳述。

TCPIOThread:IO線程,通過CommandList也可作為背景工作執行緒使用,每個線程使用asio的io_service處理多個TCPSession。

NetMessageFilterInterface:網路訊息過濾器介面(省略了Interface因為太長了),可以自定製,通常封裝組包、壓縮、加密等流程,以適應不同的邏輯層協議需求。

TCPSession:後台網路連接,不區分服務端/用戶端,負責處理網路資料的發送和接收。

外層還有兩個類:TCPServer和TCPClient,可以關聯到同一個TCPIOThreadManager,以適應多服架構中某台伺服器既是TCP伺服器又是其它伺服器的用戶端的需求。

範例程式碼:

int main(int argc, char** argv) {<br /> TCPIOThreadManager manager(1, // thread num<br /> boost::posix_time::millisec(2)); // sync interval<br /> unsigned short int port = 20000;<br /> TCPServer server({boost::asio::ip::tcp::v4(), port},<br /> manager,<br /> &MyHandler::Create,<br /> &MyFilter::Create);<br /> manager.Run();<br /> return 0;<br />} 

用戶端也類似。

 

線程同步策略:

上述線程間同步採用了Command模式,藉助了c++ 0x的function。CommandList的定義:

typedef std::list<std::function<void ()>> CommandList;
 

每個線程每隔一段時間就把要發往其它線程的Command批量發送,因為list的splice只是幾個指標的操作,這個過程可以通過自旋鎖高效的完成(psydo code):

CommandList thread1.commands_to_be_sent_;<br />CommandList thread2.commands_received_;<br />//thread1:<br />{<br /> thread1.commands_to_be_sent_.push_back(command);<br /> ...;<br /> thread2.spinlock_.lock();<br /> thread2.commands_received_.splice(thread2.commands_received_.end(),<br /> thread1.commands_to_be_sent_); //把thread1.commands_to_be_sent_串連到thread2.commands_received_的尾部<br /> thread2.spinlock_.unlock();<br />}<br />//thread2:<br />{<br /> CommandList templist;<br /> thread2.spinlock_.lock();<br /> templist.swap(thread2.commands_received_); //把commands_received_跟暫存佇列交換再處理,<br /> //減少lock的時間<br /> thread2.spinlock_.unlock();<br /> for (auto it = templist.begin(); it != templist.end(); ++it)<br /> (*it)();<br /> templist.clear();<br />}<br />

 

從TCPSessionHandler到TCPSession的NetMessageList的發送,就是通過這套機制來實現,幾乎可以忽略線程鎖開銷。

剩下的問題:NetMessage內部變長緩衝用了vector來實現,動態記憶體分配可能會帶來效率上的隱患。實際應用如果確證,可以用記憶體池,但是多線程的高效記憶體池稍微複雜。相關思路改天再寫。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.