一切像霧像雨又像風
作者:CppExplore 網址:http://www.shnenglu.com/CppExplore/網絡請求包經過網絡層(技術系列綜述(一))被解析翻譯成程序自定義的消息,之后被投遞到業務線程的線程消息隊列(技術系列綜述(二))中。業務線程在隊列的另一端取出消息,開始處理,這是本章要介紹的部分。業務處理部分:主要有會話類(Session)和會話管理類(SessionManager,常見該類為單例)。先給出類圖,后文詳細介紹:一 SessionManager的職責:(1)繼承IMsgThread(技術系列綜述(二)),調用該類的start方法,啟動業務線程(2)提供on_.../do_...方法(技術系列綜述(二)),供其它線程向業務線程投遞消息,以及消息在業務線程的處理入口。(3)主要的私有屬性是session類的容器對象。容器類的選型的依據,首先是查詢性能,之后是插入刪除的性能。array:數組下標為session對象的seesionid_(此處sessionid,不要理解為常見協議中的session字段,可以理解為session對象的索引)。可以做到插入刪除(參考內存管理chunk分配算法)查詢都在o(1)完成,缺點不能動態增大。同樣可以參考定長內存池的分配算法,動態申請255個array為一個chunk,所有chunk使用vector管理,各chunk中array編號遞增255,同樣可以達到增刪查o(1)的效率。缺點:(1)sessionid_重復使用,加上消息經過消息隊列形成的處理延遲,可能造成下一個session對象處理上一個同樣sessionid的session對象遺留下來的消息,實際使用中每個session對象有自己的狀態機,這種殘留的消息危害并不大。(2)需要自己實現,對比map的o(logn),這點細微的性能提升無任何意義(也就是減少了幾次整型之間的對比)。相比不需要自己額外實現的普通數組還算有點實用價值。vector:如果被插入的session的sessionid是遞增的,查詢可以做到折半查找logn的性能,但隨機刪除造成的內存移動是o(n),無法接受。map:以紅黑樹為基礎實現。增刪查找的性能都可以平穩的保持在o(logn),sessionid_為整型或者其operater<實現簡單的時候是最常用的容器。hash_map:哈希表,使用大量內存盡量使數據均勻分布,查詢性能分hashcode的計算(hash函數)和查找部分,hash函數一般為所有有效信息的移位計算(經典的是字符串的33算法)疊加,查找部分最理想的是0(1),最差是0(n),取決于hash函數計算結果碰撞的幾率。當sessionid_為字符串或者其operater<實現復雜的時候常用。(4)該類處理消息的方式舉例如下:(容器以map<int,session *> mapSessions_為例)
如上例所示,session管理類對消息的處理方式必須簡單固定,方便可持續維護、擴充。二 Session的職責(1)數據結構:每一路連接的業務處理部分,首先有sessionid_標記session本身,其次包含業務處理需要的必須的數據部分,另外最重要的一個數據結構就是狀態機了。(2)狀態機。狀態機標識session對象的狀態,接收外部輸入的事件,驅動狀態機運行,并作出行為響應。詳細見《技術系列之 狀態機(一)》和《技術系列之 狀態機(二)》,不多說了。(3)方法。主要分兩類:on_msg和do_event。舉例如下:
注意:1、所有有可能改變session內蘊狀態的操作都必須納入狀態機的嚴格控制,不能存在不通過狀態機即可改變session內蘊狀態的操作入口。2、如果兩個狀態對同樣的事件做出同樣的反應,并且都遷移到相同的狀態,那么這兩個是同一個狀態。3、盡可能減少狀態的個數。如果兩個狀態具有嚴格的時序關系,處理的事件不同并且有嚴格的時序關系,那么考慮合并這兩個狀態,防止狀態機膨脹。
三 總結:理解業務部分,先區分消息(Msg)和事件(Event)。1、消息(Msg):是指線程之間傳遞的數據結構,即被投遞到線程消息隊列中的數據結構。SessionManager主要職責是接收消息,通過消息映射,找到處理該消息的函數,該函數根據消息中攜帶的sessionid,找到session對象,調用該session的消息處理函數繼續后續的處理。2、事件(Event):是指被session對象中的狀態機處理的數據結構。該數據結構,在session的消息處理函數中通過消息的內容拼湊,之后交給狀態機對象處理,狀態機對象根據事件類型,通過事件映射,找到處理該事件的函數,繼續該事件的處理。3、代碼流程:一般情況下(邏輯控制部分)其它線程不能直接調用session對象,正確的調用方式是發消息SessionManager,SessionManager根據消息找到session對象再進行后續處理。4、代碼要寫的足夠呆板。 寫出好的系統關鍵在于對業務的理解,不在于對代碼技巧的玩弄。
Powered by: C++博客 Copyright © cppexplore