一 、MSMQ概述
MSMQ全称MicroSoft Message Queue,微软消息队列,是在多个不同的应用之间实现相互通信的一种异步传输模式,相互通信的应用可以分布于同一台机器上,也可以分布于相连的网络空间中的任一位置。它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中;本地或者是异地的消息接收程序再从该队列中取出发给它的消息进行处理。
消息Message是由通信的双方所需要传递的信息。
队列的类型主要包括一下几种:
“公共队列”在整个“消息队列”网络中复制,并且有可能由网络连接的所有站点访问。
“专用队列”不在整个网络中发布。相反,它们仅在所驻留的本地计算机上可用。专用队列只能由知道队列的完整路径名或标签的应用程序访问。
“管理队列”包含确认在给定“消息队列”网络中发送的消息回执的消息。指定希望 MessageQueue 组件使用的管理队列(如果有的话)。
“响应队列”包含目标应用程序接收到消息时返回给发送应用程序的响应消息。指定希望 MessageQueue 组件使用的响应队列(如果有的话)。
优点:稳定、消息优先级、脱机能力以及安全性,有保障的消息传递和执行许多业务处理的可靠的防故障机制。
缺点:MSMQ不适合于Client需要Server端实时交互情况.大量请求时候,响应延迟.
二 、安装启用服务
1. 控制面板 >> 程序 >> 打开或关闭Windows功能 >> Microsoft Message Queue(MSMQ)服务器,勾选消息队列服务所有选项
2. 我的电脑 >> 管理 >> 服务和应用程序 >> 消息队列 。出现消息队列则说明安装成功
三 、MSMQ编码应用举例
以下是几个常用查询代码
请先添加using System.Messaging;命名空间
1. 查询队列是否存在,值得注意的是,当访问远端消息时MSMQ不支持MessageQueue.Exists(string )等方法,所以建议直接使用new MessageQueue(QueuePath)查询
/// <summary> /// 查询队列是否存在 /// </summary> /// <returns></returns> public bool QueueExist() { bool queueExist = false; try { queueExist = MessageQueue.Exists(QueuePath); } catch//远端访问不支持exist,所有直接查询 { queueExist = true; } return queueExist; }
2. 创建队列,传入存储对象和注解标签
/// <summary> /// 创建队列 /// </summary> /// <param name="queueObj">发送到队列的对象</param> /// <param name="queueLable">该发送队列对象的标签</param> public void CreateQueue(object queueObj, string queueLable = "") { try { using (MessageQueue queue = QueueExist() ? new MessageQueue(QueuePath) : MessageQueue.Create(QueuePath)) { queue.Label = queueLable; if (queue.CanWrite) { queue.Send(queueObj); } } } catch (Exception ex) { throw new Exception("Error to Create Queue!", ex); } }
3. 获取队列第一条数据,并删除数据
/// <summary> /// 获取队列第一条数据,并删除数据 /// </summary> /// <param name="queueTypes"></param> /// <returns></returns> public object ReceiveOneQueue(Type[] queueTypes) { object result = null; if (QueueExist()) { using (MessageQueue mq = new MessageQueue(QueuePath)) { try { // 设置消息队列的格式化器 mq.Formatter = new XmlMessageFormatter(queueTypes); if (mq.CanRead) { Message oneMessage = mq.Receive(); // 获得消息队列中第一条消息 result = oneMessage.Body; } } catch (Exception ex) { throw new Exception("Error to query Queue!", ex); } } } return result; }
4. 获取队列第一条数据,但保留数据
/// <summary> /// 获取队列第一条数据,但保留数据 /// </summary> /// <param name="queueTypes"></param> /// <returns></returns> public object PeekOneQueue(Type[] queueTypes) { object result = null; if (QueueExist()) { using (MessageQueue mq = new MessageQueue(QueuePath)) { try { // 设置消息队列的格式化器 mq.Formatter = new XmlMessageFormatter(queueTypes); if (mq.CanRead) { Message oneMessage = mq.Peek(); // 获得消息队列中第一条消息 result = oneMessage.Body; } } catch (Exception ex) { throw new Exception("Error to query Queue!", ex); } } } return result; }
5. 调用程序
//远程连接请使用FormatName:DIRECT=ftp://222.10.xx.xx/msmq/Private$/msmqpath MSMQUtil.MSMQHelper msmqHelper = new MSMQUtil.MSMQHelper(@".\Private$\msmqpath"); msmqHelper.CreateQueue("first msmq", "first lable"); msmqHelper.CreateQueue(new msmqtestclass() { age = 25, name = "xieyang", contents = new List<string>() { "my leg", "my head" } }); var formater1 = new Type[] { typeof(string) }; object obj1 = msmqHelper.ReceiveOneQueue(formater1); var formater2 = new Type[] { typeof(msmqtestclass) }; object obj2 = msmqHelper.ReceiveOneQueue(formater2);
最常见错误: 当链接为远程时,需要给everyone读写权限。
完整代码
链接:https://pan.baidu.com/s/1lviQzuvGJFuXTqv4_7GmtA
提取码:vvxy
参考:https://docs.microsoft.com/zh-cn/dotnet/api/system.messaging?view=netframework-4.7.2
https://www.cnblogs.com/zhili/p/MSMQ.html