亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

ESFramework介紹之(7)-- 服務器代理IServer

系統 2062 0
(本文原作于2006.03.15,第一次修正于2006.06.06,修正后適用于ESFramework V0.3+)
(本文是 ESFramework 對客戶端開發的支持特性之一 ,如果要按順序閱讀,請轉到 ESFramework介紹( ))

分布式系統的構建一般有兩種模式,一是基于消息(如 Tcp http 等),一是基于方法調用(如 RPC WebService Remoting )。深入想一想,它們其實是一回事。如果你了解過 .NET Proxy ,那么你會發現,方法調用和消息請求 / 回復實際上是可以相互轉換的, .NET Proxy 的實現,就是在堆棧幀和消息之間相互轉換的過程。關于這方面的詳細論述可以參見《 .Net 本質論》一書。

我覺得 IServerAgent 是我在開發 ESFramework 期間非常滿意的一個想法,相信大家也會對它感興趣的。因為它 使得使用基于消息請求 / 回復的交互就像方法調用一樣簡單
客戶端與服務器之間的所有通信都可經過IServerAgent,包括要轉發的P2P消息。它的主要目的是:
(1)屏蔽客戶端與服務端之間的通信協議(Tcp/Udp),ITcpServerAgent、IUdpServerAgent
(2)可將異步的消息請求/回復轉化為同步的方法調用。

ESFramework 主要支持基于 Tcp Udp C/S 系統,所以客戶端和服務端之間是通過消息進行交互的。如果僅僅是客戶端發出請求、服務器給出服務這種情況很容易處理,但是如果服務端有主動發消息給客戶端的情況,事情就會變得稍微復雜。通常,客戶端會有一個專門的接收線程來負責從網絡接收數據,然后把接收的消息交給對應的處理器處理,或者,這個接收到的消息是個服務端給出的回復,那么這個回復就應該交給發出請求的請求者,但是對應的請求者在哪里了?這種回復消息與請求消息的匹配是比較繁瑣的,特別是在上述服務端可以主動給客戶端發送消息的情況下。為了簡化這個過程, IServerAgent 出現了,它用于客戶端,像它的名字一樣,可以把它當作服務器。 IServerAgent 的主要目的就是將消息請求 / 回復轉換成方法調用,就像該接口定義的一樣:
ESFramework介紹之(7)-- 服務器代理IServerAgent

public interface IServerAgent
{
/// <summary>
/// 如果超時仍然沒有回復,則拋出超時異常
/// 如果dataPriority!=DataPriority.CanBeDiscarded,則checkRespond只能為false
/// </summary>
NetMessageCommitRequest(NetMessagerequestMsg,DataPrioritydataPriority, bool checkRespond);
}

public enum DataPriority
{
High,
// 緊急命令
Common, // 如普通消息,如聊天消息
Low, // 如文件傳輸
CanBeDiscarded // 如視頻數據、音頻數據
}

首先解釋一下參數 dataPriority 的意義, dataPriority 參數僅僅對 Tcp 協議起作用,當有多個請求要同時發送時,它決定了發送的優先級。 CanBeDiscarded 表明這個消息在網絡繁忙時可以被拋棄,比如即時通訊的音頻數據、視頻數據等。關于這個數據發送的優先級機制的實現是 ITcpAutoSender ,這個組件會在后文中介紹。

CommitRequest 方法提交一個請求消息該給服務器,并返回一個回復消息給請求者。這就是一個方法調用!!!其間隱藏了通過網絡將消息發送給服務器并從服務器獲取結果的中間細節。這是怎么做到的?思路其實很簡單,只是描述起來有些復雜。主要要解決兩個問題,一是如何將請求消息與對應的回復匹配起來,二是 CommitRequest 從哪里找到匹配的回復。
對于第一個問題,相信大家還記得 IMessageHeader 定義中有個 CorrelationID 屬性,正如其名,這是一個隨機數,每生成一個新的請求消息,就會產生一個隨機數賦值給 CorrelationID 屬性,由于隨機數重復的可能性很小,所以可以把它當作是唯一的。這樣一個隨機數就唯一的標志了一個請求,當服務端收到這個請求后,就處理這個請求,并把回復消息的消息頭中的 CorrelationID 屬性設為與對應的請求消息的 CorrelationID 一樣的值,這樣,客戶端收到回復消息后,就可以和對應的請求消息一一對應起來了。

對于第二個問題的解釋,就需要涉及到 ESFramework 中支持客戶端開發的其它兩個組件: EsbPassiveDataDealer IResponseManager EsbPassiveDataDealer 是客戶端用戶處理所有接收到的消息的處理器,而 IResponseManager 組件用于暫存所有的來自服務端的回復。對于每個接收到的消息, EsbPassiveDataDealer 判斷其是否為回復,如果是,則將其交給 IResponseManager 暫存。 IResponseManager 為暫存的每個回復都設置的生存期 TTL ,如果回復在 IResponseManager 中的時間超過了這個 TTL ,則會被刪除。

你也許已經想到第二個問題的解決方法了。是的, CommitRequest 方法將請求發送到網絡之后,就定時從 IResponseManager 中尋找 CorrelationID 為請求消息頭的 CorrelationID 值的回復消息,如果找到,就返回它,否則就等待循環,直至超時拋出 TimeoutException 異常。下面給出 IResponseManager 的接口定義:
ESFramework介紹之(7)-- 服務器代理IServerAgent

public interface IResponseManager
{
void Initialize();

void PushResponse(NetMessageresponse);
NetMessagePopRespose(
int correlationID, int serviceKey); // 立即返回
NetMessagePickupResponse( int serviceKey, int corelationID); // 在TimeoutSec時間內不斷的PopRespose

/// <summary>
/// ResponseTTL如果一個回復在管理器中存在的時間超過ResponseTTL,則會被刪除。如果ResponseTTL為0,則表示不進行生存期管理
/// </summary>
int ResponseTTL{ set ;} // s

/// <summary>
/// 如果在TimeoutSec內,仍然接收不到期望的回復,則拋出異常。取0時,表示不設置超時
/// </summary>
int TimeoutSec{ set ;}
}

IServerAgent的具體實現包括TcpServerAgent和UdpServerAgent,分別支持Tcp協議和Udp協議的客戶端開發。從它們的接口定義中可以看到它們都借助于IServerAgentHelper實現自己。

public interface IServerAgentHelper
{
IEsbLoggerEsbLogger{
set ; get ;}
IContractHelperContractHelper{
set ; get ;}
INetMessageHookNetMessageHook{
set ; get ;}
IPassiveHelperPassiveHelper{
set ; get ;}

IResponseManagerResponseManager{
set ; get ;}

ISingleMessageDealerSingleMessageDealer{
set ; get ;}

IMessageDispatcher ConstructDispatcher ();
}

我們要特別注意其ConstructDispatcher方法,該方法構建了一個客戶端比較常用的消息分配器實例。在介紹 IMessageDispatcher 時,我們講過,客戶端通常不需要對消息Spy,僅僅需要Hook就可以了,所以IServerAgentHelper正是通過對各組件的組裝做到了這一點:

public IMessageDispatcherConstructDispatcher()
{
// NakeDispatcher
EsbPassiveDataDealerdealer = new EsbPassiveDataDealer( this .responseManager, this .passiveHelper, this .singleMessageDealer);
EsbPassiveDealerFactoryfactory
= new EsbPassiveDealerFactory(dealer);
NakeDispatchernakeDispatcher
= new NakeDispatcher();
nakeDispatcher.ContractHelper
= this .contractHelper;
nakeDispatcher.DataDealerFactory
= factory;

// MessageDispatcher
IMessageDispatchermessageDispatcher = new MessageDispatcher();
messageDispatcher.ContractHelper
= this .contractHelper;
messageDispatcher.NetMessageHook
= this .netMessageHook;
messageDispatcher.NakeDispatcher
= nakeDispatcher;

return messageDispatcher;
}

在IServerAgent的基礎之上,我們就可以從一個新的角度來設計客戶端的結構的,那就是采用和功能服務器一樣的插件方式。在ESFramework的支持下,我們的應用開發變得非常簡潔和簡單,所要做的主要內容就是 開發服務端的“業務功能插件”和對應的客戶端的“PassiveAddin”(客戶端插件)。 如果我們的應用已經發布投入使用,而此時用戶要求添加一項新的業務,那將是非常簡單的事情,那就是開發一個實現了新業務的功能插件動態加載到功能服務器中、再開發一個對應的客戶端插件動態加載到客戶端中,這樣就可以了。服務器不用重編譯、甚至不用停止服務;客戶端也不用重編譯、甚至不用停止使用。一切都是在運行中動態完成的。

這是如何做到的?請關注本系列文章。

轉到: ESFramework 可復用的通信框架(序)

ESFramework介紹之(7)-- 服務器代理IServerAgent


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色多网站免费视频 | 日韩在线成人 | 午夜国产精品福利在线观看 | 亚洲欧美日产综合一区二区三区 | 一级毛片卡 | 久久精热 | 97国产在线视频公开免费 | 四虎永久在线精品视频免费观看 | 老子影院午夜伦手机不卡6080 | α级毛片| 青青草论坛 | 国产美女亚洲精品久久久毛片 | 99热久久国产这里是精品 | 色老头福影院韩国激情影院 | 中文字幕日韩在线一区国内 | 亚洲国产中文字幕在线观看 | 奇米影视一区二区三区 | 香蕉在线播放 | 日本一级毛片免费播放 | 日本阿v精品视频在线观看 日本爱爱免费视频 | 9999久久| 欧美一区二区三区视频在线 | 老色99久久九九精品尤物 | 国产成人午夜精品5599 | 欧美一级毛片久久精品 | 日本高清中文字幕 | 欧美日韩成人午夜免费 | 乱码一区二区三区完整视频 | 91亚洲精品国产自在现线 | www.欧美| 欧美成人免费全网站大片 | 久久九九精品视频 | 99视频精品全部免费观看 | 中文字幕久久久久 | 欧美性一区二区三区 | 大胆国模一区二区三区伊人 | 久久香蕉国产线看观看精品yw | 国产女人18一级毛片视频 | 四虎在线观看网址 | 国产视频一区在线播放 | 天天操丝袜|