【Frank.Xu】WCF分散式開發必備知識(1):MSMQ訊息佇列

依舊伊利丹發表於2009-02-18

學習WCF是不是就不需要學習.Net Remoting、ASMX、WSE和MSMQ了?

     這個問題一直是很多開發者關注的問題.按照微軟的說法,WCF是微軟分散式應用程式開發的集大成者,學習WCF程式設計,就不需要了解其他的技術.這個說法有一定的道理.WCF的出現確實解決了很多問題,它整合了.Net平臺下所有的和分散式系統有關的技術,例如.Net Remoting、ASMX、WSE和MSMQ。以通訊(Communiation)範圍而論,它可以跨程式、跨機器、跨子網、企業網乃至於 Internet;可以以ASP.NET,EXE,WPF,Windows Forms,NT Service,COM+作為宿主(Host)。開發人員可以構建跨平臺、安全、可靠和支援事務處理的企業級互聯應用解決方案。既然WCF如此強大,開發者再不用去分別瞭解.Net Remoting,ASMX等各種技術了。

     可事實並非如此,首先,技術的更新換代沒有那麼迅速,我們接觸的工作平臺和技術文章不會因為WCF的出現而全部更新,其次作為一個開發人員,在實際開發過程要學習或者解決技術問題,必須知道其相關的概念,紮實的基礎知識畢不可少.

     在本節我們就來了解一下MSMQ的基本概念和開發過程.我們先來了解一下什麼是MSMQ:

     MSMQ全稱MicroSoft Message Queue,微軟訊息佇列,是在多個不同的應用之間實現相互通訊的一種非同步傳輸模式,相互通訊的應用可以分佈於同一臺機器上,也可以分佈於相連的網路空間中的任一位置。它的實現原理是:訊息的傳送者把自己想要傳送的資訊放入一個容器中(我們稱之為Message),然後把它儲存至一個系統公用空間的訊息佇列(Message Queue)中;本地或者是異地的訊息接收程式再從該佇列中取出發給它的訊息進行處理.

       其中兩個重要的概念。一個是訊息Message ,一個是佇列Queue。

     訊息Message是由通訊的雙方所需要傳遞的資訊,它可以是各式各樣的媒體,如文字、聲音、圖象等等。訊息最終的理解方式,為訊息傳遞的雙方事先商定,這樣做的好處是,一是相當於對資料進行了簡單的加密,二則採用自己定義的格式可以節省通訊的傳遞量。訊息可以含有傳送和接收者的標識,只有指定的使用者才能看到回執。時間戳,便於接收方對某些與時間相關的應用進行處理。截止時間,指定時間內訊息還未到達則作廢。

佇列的型別主要包括一下幾種:

“公共佇列”在整個“訊息佇列”網路中複製,並且有可能由網路連線的所有站點訪問。
“專用佇列”不在整個網路中釋出。相反,它們僅在所駐留的本地計算機上可用。專用佇列只能由知道佇列的完整路徑名或標籤的應用程式訪問。
“管理佇列”包含確認在給定“訊息佇列”網路中傳送的訊息回執的訊息。指定希望 MessageQueue 元件使用的管理佇列(如果有的話)。
“響應佇列”包含目標應用程式接收到訊息時返回給傳送應用程式的響應訊息。指定希望 MessageQueue 元件使用的響應佇列(如果有的話)。

     訊息佇列Queue是傳送和接收訊息的公用儲存空間,它可以存在於記憶體中或者是物理檔案中。訊息可以以兩種方式傳送,即快遞方式(express)和可恢復模式(recoverable),它們的區別在於,快遞方式為了訊息放置於記憶體中,可恢復模式放於物理磁碟上(詳細參見MSDN).

 

     瞭解到訊息佇列MSMQ相關的基本概念以後,我們知道它的

優點:穩定、訊息優先順序、離線能力以及安全性,有保障的訊息傳遞和執行許多業務處理的可靠的防故障機制。

缺點:MSMQ不適合於Client需要Server端實時互動情況.大量請求時候,響應延遲.

     優點決定了它的鬆耦合的特性,訊息佇列同樣是實現SOA物件導向的架構的方式之一.現在我們就來看看簡單的MSMQ程式設計.

     要在.net平臺上進行MSMQ的開發,需要配置開發環境,安裝訊息佇列,具體的安裝過程可以baidu,直接在安裝光碟裡查詢安裝windows元件,選擇訊息佇列安裝即可.


 安裝結束後,可以在我的電腦--管理--訊息佇列

這個證明你已經安裝成功.下面就可以來使用Visual Stdudio進行開發了.

首先,建立一個控制檯專案(當然你也可以建立Web或者Winform應用程式).新增專案引用System.Messaging,因為訊息佇列相關的類庫全部封裝在System.Messaging.dll程式集裡了.下面我們就來寫自己的程式碼.

 

Code
 1static void Main(string[] args)
 2        {
 3            //Create a public Queue
 4            if (!MessageQueue.Exists(@".\FrankMSMQ"))//判斷此路徑下是否已經有該佇列
 5            {
 6                using (MessageQueue mq = MessageQueue.Create(@".\FrankMSMQ"))
 7                {
 8                    mq.Label = "FrankPublicQueue";設定佇列標籤
 9                    Console.WriteLine("FrankPublicQueue is Created:");
10                    Console.WriteLine("Path is {0}:", mq.Path);
11                    Console.WriteLine("FrankPublicQueue' name is {0}:", mq.QueueName);
12                    //Console.Read();
13                    mq.Send("MSMQ Message", "Frank.Xu");//傳送訊息
14                }
15            }//Create a private Queue私有訊息佇列
16            if (!MessageQueue.Exists(@".\Private$\FrankMSMQ"))
17            {
18                using (MessageQueue mq = MessageQueue.Create(@".\Private$\FrankMSMQ"))
19                {
20                    mq.Label = "FrankPrivateQueue";
21                    Console.WriteLine("FrankPrivateQueue is Created:");
22                    Console.WriteLine("Path is {0}:", mq.Path);
23                    Console.WriteLine("FrankPrivateQueue' name is {0}:", mq.QueueName);
24                    //Console.Read();
25                    mq.Send("MSMQ Private Message", "Frank.Xu");
26                }
27            }
28
29            //Get all public queues and send new messages
30            foreach (MessageQueue mq in MessageQueue.GetPublicQueues())//遍歷所有的公共訊息佇列
31            {
32                mq.Send("Sending MSMQ public message" + DateTime.Now.ToLongDateString(),"Frank.Xu");//傳送公共訊息
33                //string mName = mq.MachineName;
34                Console.WriteLine("Public Message is sent to {0}:", mq.Path);
35            }
36            //find private queues and send new messages
37            if (MessageQueue.Exists(@".\Private$\FrankMSMQ"))//獲得私有的訊息佇列
38            {
39                MessageQueue mq = new MessageQueue(@".\Private$\FrankMSMQ");
40                mq.Send("Sending MSMQ private message" + DateTime.Now.ToLongDateString(), "Frank.Xu");//傳送訊息到私有的訊息佇列裡
41                Console.WriteLine("Private Message is sent to {0}:", mq.Path);
42            }
43            Console.Read();
44        }
     比較重要的類就是MessageQueue,這行程式碼建立訊息佇列 MessageQueue mq = MessageQueue.Create(@".\FrankMSMQ"),引數是存放訊息佇列的位置.這個基本就完成了建立和傳送訊息的主程式.下面我們來建立一個客戶端,來訪問訊息佇列,獲取訊息,同樣建立一個控制檯應用程式,新增引用和程式碼:

 

Code
 1namespace MSMQClient
 2{
 3    class Program
 4    {
 5        static void Main(string[] args)
 6        {
 7            //Get public queue message
 8            if (MessageQueue.Exists(@".\FrankMSMQ"))//判斷是否存在訊息佇列
 9            {
10
11                using(MessageQueue mq = new MessageQueue(@".\FrankMSMQ"))//建立訊息佇列物件
12                {
13                    mq.Formatter = new XmlMessageFormatter(new string[] { "System.String" });//設定訊息佇列的格式化器
14                    //mq.Send("Sample Message", ":Label");
15                    Message msg = mq.Receive();//從佇列接受訊息
16                    Console.WriteLine("Received MSMQ Message is :{0}", msg.Body);//輸出訊息
17                }
18                    //Console.Read();
19            }
20            //Get private queue message
21            if (MessageQueue.Exists(@".\Private$\FrankMSMQ"))//判斷私有訊息是否存在
22            {
23
24                using (MessageQueue mq = new MessageQueue(@".\Private$\FrankMSMQ"))
25                {
26                    mq.Formatter = new XmlMessageFormatter(new string[] { "System.String" });//設定訊息佇列格式化器
27                    //mq.Send("Sample Message", ":Label");
28                    Message msg = mq.Receive();//接收訊息
29                    Console.WriteLine("Received MSMQ Private Message is: {0}", msg.Body);//輸出訊息
30                }
31                   
32            }
33            Console.Read();
34        }
35    }
36}
37
     訊息接收同樣需要例項化一個訊息佇列物件, using(MessageQueue mq = new MessageQueue(@".\FrankMSMQ"))負責建立訊息佇列物件.其次 mq.Formatter = new XmlMessageFormatter(new string[] { "System.String" })這行程式碼負責設定訊息佇列的格式化器,因為訊息的傳遞過程中存在格式化的問題.我們接收訊息的時候必須指定訊息佇列的格式化屬性Formatter,佇列才能接受訊息.XmlMessageFormatter的作用是進行訊息的XML序列化.BinaryMessageFormatter則把訊息格式化為二進位制資料進行傳輸.ActiveXMessageFormatter把訊息同樣進行二進位制格式化,區別是可以使用COM讀取佇列中的訊息.

     當然訊息佇列還可以傳送複雜的物件,前提是這個物件要可序列化,具體的格式取決與佇列的格式化器設定.此外訊息佇列還支援事務佇列來確保訊息只傳送一次和傳送的順序.

     最近在研究SOA,所以系統系統學習一下WCF及其相關的技術,以上就是這個訊息佇列的基本的概念和簡單的程式設計實現.下一節是關於.Net Remoting的基礎知識和開發的文章.~

我準備把WCF相關的幾個知識點都系統整理一下,包括程式碼的實現.發出來一起與大家交流學習~

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15783504/viewspace-555165/,如需轉載,請註明出處,否則將追究法律責任。

相關文章