一、引言

  Windows Communication Foundation(WCF)是Microsoft為構建面向服務的應用進程而提供的統一編程模型,該服務模型提供了支持鬆散耦合和版本管理的串行化功能,並提供了與消息隊列(MSMQ)、COM+、Asp.net Web服務、.NET Remoting等微軟現有的分佈式系統技術。利用WCF平台,開發人員可以很方便地構建面向服務的應用進程(SOA)。可以認為,WCF是對之前現有的分佈式技術(指的是MSMQ、.NET Remoting和Web 服務等技術)的集成和擴展,既然這樣,我們就有必要首先了解下之前分佈式技術,只有這樣才能更深刻地明白WCF所帶來的好處。今天就分享下MSMQ這種分佈式技術。

二、MSMQ的介紹

   MSMQ全稱是Microsoft Message Queue——微軟消息隊列。它是一種異步傳輸模式,可以在不同的應用之間實現相互通信,相互通信的應用可以分佈在同一台機器上,也可以分佈於相連的網絡空間中的任一位置。

2.1 MSMQ 工作原理

  MSMQ的實現原理是:消息的發送者把自己想要發送的信息放入一個容器,然後把它保存到一個系統公用空間的消息隊列中,本地或異地的消息接收進程再從該隊列中取出發給它的消息進行處理。

  消息隊列是一個公用存儲空間,它可以存在於內存中或物理文檔中,因此,消息以兩種方式發送,即快遞方式和可恢復模式。它們的區別是消息存儲位置的不同,快遞方式,為了消息的快速傳遞,所以把消息放置在內存中,而不放在物理磁盤上,以獲得較高的處理能力;而可恢復模式在傳送過程的每一步驟中,都把消息寫入物理磁盤上,這樣當保存消息隊列的機器發生故障而重新啟動後,可以把發送的消息恢復到故障發送之前的狀態,以獲得更好的消息恢復能力。消息隊列可以放在發送方、接收方所在的機器上,也可以單獨放置在另外一台機器上。另外,採用消息隊列機制,發送方不必要擔心接收方是否啟動,是否發生故障等因素,只要消息成功發送出去,就可以認為處理完成,而實際上對方可能甚至未開機,或者實際消息傳遞到對方可能在第二天。MSMQ機制類似QQ消息傳遞機制。下圖演示了MSMQ的實現原理。

MSMQ消息隊列-LMLPHP

  MSMQ中主要有兩個概念。

  •   一個是消息Message:Message是通信雙方需要傳遞的消息,它可以是文本、圖片、視頻等。消息包含發送和接收者的標識,只有指定的用户才能取得消息。
  •   一個是隊列Queue:用來保存消息的存儲空間,MSMQ中主要包括以下幾種隊列類型:
    • 公共隊列:在整個消息隊列網絡中複製,有可能由網絡連接的所有站點訪問。路徑格式為:機器名稱\隊列名稱
    • 專用隊列(或叫私有隊列):不在整個網絡中發佈,它們僅在所駐留的本地計算機上可用,專用隊列只能由知道隊列的完整路徑名稱或標籤的應用進程訪問。路徑格式為:機器名稱\Private$\隊列名稱
    • 日誌隊列:包含確認在給定“消息隊列中發送的消息回執消息”。路徑格式為:機器名稱\隊列名稱\Journal$
    • 響應隊列:包含目標應用進程接收到消息時返回給發送應用進程的響應消息,包括機器日誌隊列、機器死信隊列和機器事務死信隊列。
      • 機器日誌隊列對應的格式為:機器名稱\Journal$;
      • 機器死信隊列對應的格式為:機器名稱\Deadletter$;
      • 機器信道死信隊列對應的格式為:機器名稱\XactDeadletter$。

 

2.2 隊列引用説明

  當創建了一個MessageQueue實例之後,就應指明和哪個隊列進行通信,在.NET中有3種訪問指定消息隊列的方法:

  • 使用路徑,消息隊列的路徑被機器名和隊列名唯一確定,所以可以用消息隊列路徑來指明使用的消息隊列。
  • 使用格式名(format name),它是由MSMQ在消息隊列創建時生成的唯一標識,個使命不由用户指定,而是由隊列管理者自動生成的GUID。
  • 使用標識名(label),它是消息隊列創建時由消息管理者指定的帶有意義的名字。

 

三、消息隊列的優缺點

   採用消息隊列的好處是:由於是異步通信,無論是發送方還是接收方都不同等待對方返回成功消息,就可以執行餘下的代碼,大大提高了處理的能力;在信息傳遞過程中,具有故障恢復能力;MSMQ的消息傳遞機制使得通信的雙方具有不同的物理平台成為可能。

  消息隊列缺點是不適合Client需要Server端實時交互情況,大量請求時候,響應可能延遲。

四、利用MSMQ開發分佈式應用

4.1 環境準備

   要想在.NET平台進行MSMQ的開發,需要安裝消息隊列,你需要打開控制皮膚->進程->打開或關閉Windows功能,勾選消息隊列服務所有選項,具體操作如下圖所示:

MSMQ消息隊列-LMLPHP

  勾選完之後點擊確定之後,可以在我的電腦->管理->服務和應用進程->消息隊列 看到下面的圖:

MSMQ消息隊列-LMLPHP

  看到上面這個圖代表你已經成功配置了MSMQ的開發環境,下面就可以使用Visual Studio 進行開發。注意,對特定類型隊列的操作代碼,一定要成功安裝對應的隊列類型。

4.2 使用MSMQ開發分佈式應用

  首先,實現服務器端。創建一個控制枱項目,添加System.Messaging引用,因為消息隊列的類全部封裝在System.Messaging.dll進程集裏。具體服務端的代碼如下:

1 using System;
 2 using System.Messaging;
 3
 4 namespace MSMQServer
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             // 創建一個公共隊列,公共隊列只能創建在域環境裏
11             //if (!MessageQueue.Exists(@".\LearningHardMSMQ")) // 判斷此路徑下是否已經有該隊列
12             //{
13             //    using (MessageQueue mq = MessageQueue.Create(@".\LearningHardMSMQ"))
14             //    {
15             //        mq.Label = "LearningHardQueue"; // 設置隊列標籤
16             //        Console.WriteLine("已經創建了一個公共隊列");
17             //        Console.WriteLine("路徑為:{0}", mq.Path);
18             //        Console.WriteLine("隊列名字為:{0}", mq.QueueName);
19             //        mq.Send("MSMQ Message", "Leaning Hard"); // 發送消息
20             //    }
21             //}
22
23             //if (MessageQueue.Exists(@".\Private$\LearningHardMSMQ"))
24             //{
25                   // 刪除消息隊列
26             //    MessageQueue.Delete(@".\Private$\LearningHardMSMQ");
27             //}
28             // 創建一個私有消息隊列
29             if (!MessageQueue.Exists(@".\Private$\LearningHardMSMQ"))
30             {
31                 using (MessageQueue mq = MessageQueue.Create(@".\Private$\LearningHardMSMQ"))
32                 {
33                     mq.Label = "LearningHardPrivateQueue";
34                     Console.WriteLine("已經創建了一個私有隊列");
35                     Console.WriteLine("路徑為:{0}", mq.Path);
36                     Console.WriteLine("私有隊列名字為:{0}", mq.QueueName);
37                     mq.Send("MSMQ Private Message", "Leaning Hard"); // 發送消息
38                 }
39             }
40
41             // 遍歷所有的公共消息隊列
42             //foreach (MessageQueue mq in MessageQueue.GetPublicQueues())
43             //{
44             //    mq.Send("Sending MSMQ public message" + DateTime.Now.ToLongDateString(), "Learning Hard");
45             //    Console.WriteLine("Public Message is sent to {0}", mq.Path);
46             //}
47
48             if (MessageQueue.Exists(@".\Private$\LearningHardMSMQ"))
49             {
50                 // 獲得私有消息隊列
51                 MessageQueue mq = new MessageQueue(@".\Private$\LearningHardMSMQ");
52                 mq.Send("Sending MSMQ private message" + DateTime.Now.ToLongDateString(), "Leaning Hard");
53                 Console.WriteLine("Private Message is sent to {0}", mq.Path);
54             }
55
56             Console.Read();
57         }
58     }
59 }

 

  服務器端代碼需要注意的是,公共隊列只能在域環境中創建,由於我的個人電腦沒有加入域環境,所以不能創建公共隊列,從開始的消息隊列的截圖也可以看出,在圖中並沒有安裝公共隊列。

  實現完服務器端之後,自然就是完成客户端。MSMQ進程的原理主要是:服務器端把消息發送到共享的消息隊列中,然後,客户端從這個共享的消息隊列中取出消息進行處理。具體客户端的實現代碼如下所示:

1 using System;
 2 using System.Messaging; // 需要添加System.Messaging引用
 3
 4 namespace MSMQClient
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             if (MessageQueue.Exists(@".\Private$\LearningHardMSMQ"))
11             {
12                 // 創建消息隊列對象
13                 using (MessageQueue mq = new MessageQueue(@".\Private$\LearningHardMSMQ"))
14                 {
15                     // 設置消息隊列的格式化器
16                     mq.Formatter = new XmlMessageFormatter(new string[] { "System.String" });
17                     foreach (Message msg in mq.GetAllMessages())
18                     {
19                         Console.WriteLine("Received Private Message is: {0}", msg.Body);
20                     }
21
22                     Message firstmsg = mq.Receive(); // 獲得消息隊列中第一條消息
23                     Console.WriteLine("Received The first Private Message is: {0}", firstmsg.Body);
24                 }
25             }
26             Console.Read();
27         }
28     }
29 }

4.3 運行演示

  經過上面步驟,我們已經完成了MSMQ分佈式進程的實現了,下面看看如何運行該進程來查看效果。

  首先,自然要啟動服務器,右鍵MSMQServer項目->調試->啟動新實例來啟動服務器,具體步驟如下圖所示:

MSMQ消息隊列-LMLPHP

  運行成功之後,你將到服務器發送消息成功的控制枱界面,效果圖如下所示:

MSMQ消息隊列-LMLPHP

  接下來運行客户端來從消息隊列中取得消息並顯示在控制枱中,採用和服務器相同的方式來啟動客户端,右鍵MSMQClient->調試->啟動新實例,看到客户端的效果如下圖所示:

MSMQ消息隊列-LMLPHP

  從上圖可以看出,客户端確實成功地取得了消息隊列中的消息。

    以上MSMQ進程需要特別注意是:MessageQueue.Receive()是取出消息隊列中隊列中的第一條消息,並從消息隊列中移除它(MSDN中文翻譯上是錯誤,MSDN寫的是不移除,而英文原文是移除),而實際結果也是移除的,如果你再運行一次客户端時,你會發現消息隊列中只有一條消息,具體運行效果如下圖所示:

MSMQ消息隊列-LMLPHP

五、總結

   到這裏,MSMQ的內容就分享結束, 其MSMQ的實現原理也非常簡單,一句話慨括就是服務器把消息放在一個公共的地方,這個地方叫做消息隊列,而其他客户端可以從這個地方取出消息進行處理。

 

關鍵詞:消息 隊列 msmq mq 可以 messagequeue 機器 發送 private message

相關推薦:

關於MSMQ

msmq

簡單易用的.NET免費開源RabbitMQ操作組件EasyNetQ解析

C#使用消息隊列(MSMQ)

分佈式消息隊列 RocketMQ 源碼分析 —— Message 拉取與消費(下)

Message Queuing(MSMQ)演練

消息隊列MSMQ的使用

分佈式消息隊列 RocketMQ 源碼分析 —— Message 順序發送與消費

MQ單一消息完整流程


转载:https://hk.saowen.com/a/73d135ba3588d6930d406917300aa9d76d4234b3b435af30b837d2594ea8c4e2
10-17 18:00