一、引言
MSMQ全称MicroSoft Message Queue,微软消息队列,是在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任一位置。它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中,本地或者异地的消息接收程序再从该队列中取出发给它的消息进行处理。
消息Message是由通信的双方所需要传递的信息。消息是MSMQ的存储对象,封装为System.Messaging.Message对象,它由一个主体(body)和若干属性构成,其中我们的用户数据通常被序列化装入body主体中,这也是我们称它为数据容器的原因。除了body属性,还有几个属性相对来说比较重要:Priority(消息的优先级),Label(用户定义的消息标识),Formatter(消息的序列组件,当用户将复杂类型数据填充到body中,用户的数据会先被序列化)。
队列分事务性队列和非事务性队列,默认创建的是非事务性队列。当我们勾选事务性复选框,就会创建事务性队列。那么什么是事务性队列呢?事务性队列将消息保存在磁盘上,实现了持久化,也就是说当关机断电后,下次再启动机器,我们的消息依然保存在队列里面,而非事务性队列则将消息保存在内存中,也就是说重启电脑后,队列里面的消息将不存在了。
队列的类型主要包括以下几种:
“公共队列”在整个“消息队列”网络中复制,并且有可能由网络连接的所有站点访问。
“专用队列”不在整个网络中发布,相反,它们仅在所驻留的本地计算机上可用。专用队列只能由知道队列的完整路径名或标签的应用程序访问。
“管理队列”包含确认在给定“消息队列”网络中发送的消息回执的消息。指定希望 MessageQueue 组件使用的管理队列(如果有的话)。
“响应队列”包含目标应用程序接收到消息时返回给发送应用程序的响应消息。指定希望 MessageQueue 组件使用的响应队列(如果有的话)。
优点:稳定、消息优先级、脱机能力以及安全性,有保障的消息传递和执行许多业务处理的可靠的防故障机制。
缺点:MSMQ不适合于Client需要Server端实时交互情况;大量请求的时候响应延迟。
二、安装
在运行中输入appwiz.cpl->打开或关闭 Windows 功能->Microsoft Message Queue (MSMQ) 服务器。
安装成功后,在运行中输入compmgmt.msc->服务和应用程序->消息队列。
右键消息队列->属性,可更改默认存储路径等。
三、示例演示
注意:需引用System.Messaging。
class Program { static void Main(string[] args) { #region MSMQ入门一 //创建消息队列,默认存储路径:C:\Windows\System32\msmq\storage if (MessageQueue.Exists(@".\Private$\HelloMSMQ")) MessageQueue.Delete(@".\Private$\HelloMSMQ"); //删除消息队列HelloMSMQ if (MessageQueue.Exists(@".\Private$\WorldMSMQ")) MessageQueue.Delete(@".\Private$\WorldMSMQ"); //删除消息队列WorldMSMQ MessageQueue mqHello = MessageQueue.Create(@".\Private$\HelloMSMQ"); MessageQueue mqWorld = MessageQueue.Create(@".\Private$\WorldMSMQ"); //发送消息 mqHello.Send("Hi World,I am Hello.", "mqHello1"); mqHello.Send("Are you free?", "mqHello2"); mqWorld.Send("Hi Hello,I am World.", "mqWorld1"); mqWorld.Send("I guess I'll be free.", "mqWorld2"); //返回本机所有私有队列的消息 foreach (MessageQueue item in MessageQueue.GetPrivateQueuesByMachine("cx168")) { item.Formatter = new XmlMessageFormatter(new string[] { "System.String" }); Message[] messages = item.GetAllMessages(); foreach (Message message in messages) { Console.WriteLine($"Label: {message.Label} Body: {message.Body}"); } } //返回指定队列的消息 if (MessageQueue.Exists(@".\Private$\HelloMSMQ")) { using (MessageQueue theOne = new MessageQueue(@".\Private$\HelloMSMQ")) { Console.WriteLine(); //设置消息队列格式化器 theOne.Formatter = new XmlMessageFormatter(new string[] { "System.String" }); //接受但不删除消息 Message msg = mqHello.Peek(); Console.WriteLine($"Label: {msg.Label} Body: {msg.Body}"); //接受并删除消息 msg = mqHello.Receive(); Console.WriteLine($"Label: {msg.Label} Body: {msg.Body}"); msg = mqHello.Peek(); Console.WriteLine($"Label: {msg.Label} Body: {msg.Body}"); //删除所有消息 mqHello.Purge(); Console.WriteLine($"mqHello count: {mqHello.GetAllMessages().Count()}"); } } Console.Read(); #endregion } }
运行结果如下:
参考自:
https://www.cnblogs.com/tenghoo/archive/2009/11/05/1596456.html
https://www.cnblogs.com/shaoshun/p/3800208.html