上一篇讲了搭建VMware虚拟机实现与宿主机相互通信,环境已经就绪,现在就可以做MSMQ的分布式开发了。

本篇准备分四点介绍MSMQ:

1.MSMQ简介

2.MSMQ的安装

3.MSMQ编程开发

4.Demo下载

一、MSMQ简介

MSMQ本质上是一种消息传递协议,它允许在单独的服务端/客户端运行的应用程序间已可靠的方式通信。队列用来临时存储消息,服务器端向队列发送消息,客户端从队列读取消息。这就使得即使服务器端和客户端不在同一网络中,不能直接访问彼此,也能通过队列进行通信。相比之下,sockets和其他网络协议就不能做到这一点,它们只能在服务器端和客户端能够直接相互通信的情况下才有效。

MSMQ诞生于1997年,它已经被广泛使用在企业级软件中。Microsoft已经把MSMQ合并到它的消息技术框架WCF当中。在WCF中,MSMQ被用于提供安全,可靠的传输和一个统一的编程模型,同时还兼容通信标准。

MSMQ负责企业内部和外部应用程序之间可靠地传递信息。MSMQ会把发送失败的消息放置在一个队列里面,一旦目标可以访问,MSMQ会重新发送消息到目标中。它也支持消息的安全性和优先级机制。如果要消息超时或者因为其他原因失败,可以创建死信队列进行查看。

MSMQ也支持事务。它允许对多个队列的多个操作在一个事务中进行,从而保证要么全不执行,要么全部不执行。微软分布式事务处理协调器(MSDTC)支持MSMQ和其他资源的事务性访问。

微软消息队列使用以下端口:

  • TCP: 1801
  • RPC: 135, 2101*, 2103*, 2105*
  • UDP: 3527, 1801
  • 消息队列初始化的时候,如果RPC端口正在使用,那么这些端口号有可能被增加11。查询端口135发现该2XXX端口。

各个操作系统中使用的MSMQ版本如下:

  • Version 1.0 (May 1997). Supports Windows 95, Windows NT 4.0 SP3, Windows 98 and Windows Me.
  • Version 2.0, included with Windows 2000.
  • Version 3.0, included with Windows XP (Professional, not Home Edition) and Windows Server 2003.
  • Version 4.0, part of Windows Vista and Windows Server 2008.
  • Version 5.0, part of Windows 7 and Windows Server 2008 R2.
  • Version 6.0, part of Windows 8 and Windows Server 2012.
  • Version 6.3, part of Windows Server 2012 R2.

二、MSMQ的安装

本篇MSMQ部署在Windows Server 2008 R2中。win7/Windows Server 2008 R2 支持的MSMQ的Feature看表格:

Feature (Windows 7 / Windows Server 2008 R2) Description
Microsoft Message Queue (MSMQ) Server Core / MSMQ Services This is the core service used for sending and receiving messages.
MSMQ Active Directory Domain Services Integration / Directory Service Integration This feature enables publishing of queue properties to Active Directory Domain Services (AD DS), default authentication and encryption of messages using certificates registered in AD DS, and routing of messages across Windows sites. MSMQ Active Directory Integration requires the computer to be joined to a domain.
MSMQ HTTP Support / HTTP Support This feature enables the sending of messages over Hypertext Transfer Protocol (HTTP). MSMQ HTTP support requires that Internet Information Services (IIS) be installed on the local computer.
MSMQ Triggers / Message Queuing Triggers This feature enables the invocation of a Component Object Model (COM) component or an executable file, depending on the filters that you define for the incoming messages in a given queue.
MSMQ DCOM Proxy / Message Queuing DCOM Proxy This feature enables Message Queuing applications to use a MSMQ COM application programming interface (API) to connect to a remote Message Queuing server.
Multicasting Support / Multicasting Support This feature supports multicasting messages to a multicast IP address and associating a queue with a multicast IP address.
Routing Service

This feature routes messages between different sites and within a site.

(note:The Routing Service feature is only available on Windows Server 2008 R2.)

MSMQ作为功能组件被集成在系统当中,在Window Server 2008 R2 安装MSMQ非常简单,点击【开始\控制面板\管理工具\服务器管理器\功能\添加功能\依次展开MSM\MSMQ服务】。注意:要使用【路由服务】,服务器必须加入域。如图:

三、MSMQ编程开发

在讲MSMQ编程开发之前,有必要先了解一下MSMQ的队列。在MSMQ中,队列用来临时存储不同类型的消息。队列在逻辑上被划分为两组:应用程序队列和系统队列。应用程序队列可以被应用程序创建,系统队列由MSMQ创建。

应用程序队列包括消息队列,管理队列,响应队列和报告队列。

消息队列,应用程序间可以通过消息队列里面的消息进行通信,应用程序可以通过消息队列发送和接收消息。注意:应用程序创建队列后,在计算机管理单元中的消息队列中总是显示小写。然而,在MSMQ中,消息队列的名称是大小写敏感的,所以在代码中使用队列名称的时候要十分注意。例如,应用程序创建了一个名为MYQUEUE的队列,在计算机的管理单元中显示为myqueue。在应用程序中访问这个队列时,名称一定要使用大写的MYQUEUE,如果使用小写myqueue,就会抛出一个异常。

管理队列,在发送消息的应用程序中可以指定管理队列,管理队列存储MSMQ发送的确认消息,确认消息标识应用程序发送的消息是否成功。

响应队列,发送消息的应用程序可以指定响应队列,接收消息的应用程序发送响应消息到响应队列。

报告队列,消息每次通过MSMQ路由服务器传递,MSMQ会发送一条报告消息进行跟踪,报告消息存储在报告队列中。报告队列由发送程序指定和启用。

系统队列由MSMQ或者MSMQ管理员创建,包括日志队列和死信队列。

日志队列,当应用程序队列被创建后,MSMQ自动创建一条日志消息跟踪被读取的消息。

死信队列,保存未能被正确发送的消息。MSMQ提供两种死信队列,一种是非事务死信队列,一种是事务性死信队列。

队列的基本概念讲完了,下面就开始讲讲具体的使用。园子里已经有很多很好的文章介绍MSMQ消息队列的创建,消息的发送和消息的接收,我就不再重复造轮子了。但是在真实使用场景中,如果消息发送不成功,而消息又非常重要每个消息都必须处理,这种情况该怎么使用MSMQ,园子里介绍的文章倒不是很多,所以这里我就重点介绍一下管理队列和死信队列的用法。

  1. 新建消息发送控制台应用程序TestAck,黏贴一下代码:

public class MyNewQueue{static void Main(string[] args){// Create a new instance of the class.MyNewQueue myNewQueue = new MyNewQueue();// Create new queues.CreateQueue(".\\private$\\myQueue");CreateQueue(".\\private$\\myAdministrationQueue");// Send messages to a queue.myNewQueue.SendMessage();Console.ReadLine();}//**************************************************// Creates a new queue.//**************************************************public static void CreateQueue(string queuePath){try{if (!MessageQueue.Exists(queuePath)){MessageQueue.Create(queuePath);}else{Console.WriteLine(queuePath + " already exists.");}}catch (MessageQueueException e){Console.WriteLine(e.Message);}}//**************************************************// Sends a string message to a queue.//**************************************************public void SendMessage(){// Connect to a queue on the local computer.MessageQueue myQueue = new MessageQueue($".\\private$\\myQueue");;myQueue.Label = "label1";// Create a new message.Message myMessage = new Message("Original Message");myMessage.AdministrationQueue = new MessageQueue(".\\private$\\myAdministrationQueue");myMessage.AcknowledgeType = AcknowledgeTypes.NegativeReceive;myMessage.UseDeadLetterQueue = true;myMessage.TimeToBeReceived = TimeSpan.FromSeconds(2);myMessage.Label = "label1";// Send the Order to the queue.Thread.Sleep(TimeSpan.FromSeconds(3));myQueue.Send(myMessage);return;}}

myMessage.AdministrationQueue = new MessageQueue(".\\private$\\myAdministrationQueue");

指定消息的管理队列,管理队列的创建很普通消息队列是一样的。

myMessage.UseDeadLetterQueue = true;

指定消息使用死信队列,消息发送不成功时,系统会发送消息的副本到死信队列。

myMessage.AcknowledgeType = AcknowledgeTypes.NegativeReceive;

指定当消息队列未能接收消息时,发送确认消息到管理队列。AcknowledgeTypes是一个枚举类型,枚举值:

PositiveArrival

一个掩码,用于在原始消息到达队列时请求肯定确认。

PositiveReceive

一个掩码,用于在成功从队列检索到原始消息时请求肯定确认。

NegativeReceive

一个掩码,用于当未能从队列接收原始消息时请求否定确认。

None

一个掩码,用于请求不发送任何确认消息(无论是肯定的还是否定的)。

NotAcknowledgeReachQueue

一个掩码,用于在原始消息不能到达队列时请求否定确认。当到达队列时间计时器过期时或不能对消息进行身份验证时,可能请求否定确认。

NotAcknowledgeReceive

一个掩码,用于当发生错误时请求否定确认,防止在其接收时间计时器过期前从队列接收原始消息。

FullReachQueue

一个掩码,用于在原始消息到达队列时请求肯定确认,或者用于到达队列时间计时器过期后请求否定确认,或者用于不能对原始消息进行身份验证时请求否定确认。

FullReceive

一个掩码,用于在接收时间计时器过期前从队列收到原始消息时请求肯定确认,否则请求否定确认。

备注:确认消息是系统生成的非事务性消息,它们标识由应用程序发送的消息是否成功发送到目标队列,也可以标识是消息否被应用程序成功读取。

myMessage.TimeToBeReceived = TimeSpan.FromSeconds(2);

Thread.Sleep(TimeSpan.FromSeconds(3));

myQueue.Send(myMessage);

模拟消息发送超时,消息队列未能接收消息的情况。消息的TimeToBeReceived属性指定队列接收消息的超时时间。

代码执行后,查看计算机管理单元中的消息队列情况,由于发送消息超时,所以消息队列myQueue中没有接收到消息;管理队列被指定为当消息发送不成功时接收确认消息,所以管理队列中由系统自动生成了一条确认消;消息指定使用死信队列,所以系统同时发送消息的副本到死信队列。如下图:

2.新建接收消息控制台应用程序AckClient,黏贴以下代码

class ReceiveClient{static void Main(string[] args){new ReceiveClient().ReceiveAckMessage();new ReceiveClient().ReceiveDeadLetterMessage();Console.ReadLine();}private void CreateQueue(string path){try{if (!MessageQueue.Exists(path)){MessageQueue.Create(path);}else{Console.WriteLine("该队列已存在!");}}catch (MessageQueueException ex){throw;}}private void ReceiveAckMessage(){MessageQueue myQueue = new MessageQueue(".\\private$\\myAdministrationQueue");myQueue.MessageReadPropertyFilter.CorrelationId = true;myQueue.MessageReadPropertyFilter.Acknowledgment = true;myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });MessageQueue mySendQueue = new MessageQueue(".\\private$\\myQueue");mySendQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });try{Message myMessage = myQueue.Receive(TimeSpan.FromSeconds(3));Console.WriteLine("_______________________________");Console.WriteLine("Ack Message body: " + myMessage.Body.ToString());Console.WriteLine("Ack Message Id: " + myMessage.Id);Console.WriteLine("Correlation Id: " + myMessage.CorrelationId);Console.WriteLine("Acknowledgment Type: " + myMessage.Acknowledgment.ToString());Console.WriteLine("_______________________________");}catch (MessageQueueException ex){throw;}}private void ReceiveDeadLetterMessage(){MessageQueue myQueue = new MessageQueue("FormatName:Direct=os:.\\System$;DEADLETTER");myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });myQueue.MessageReadPropertyFilter.CorrelationId = true;try{Message myMessage = myQueue.Receive(TimeSpan.FromSeconds(3));Console.WriteLine("__________________________________");Console.WriteLine("Dead Letter Id: " + myMessage.Id);Console.WriteLine("Dead Letter Body: " + myMessage.Body.ToString());Console.WriteLine("__________________________________");}catch (MessageQueueException ex){throw;}}}

ReceiveAckMessage()方法从管理队列接收确认消息。
myMessage.CorrelationId: 确认消息的CorrelationId属性标识原始消息的消息ID
myMessage.Acknowledgment: 确认消息的Acknowledgment属性标识确认消息的类型。

ReceiveDeadLetterMessage()方法从死信队列接收死信消息。
myMessage.Body: 死信消息时原始消息的副本,死信消息的body属性值与原始消息的body属性值相同。
myMessage.Id: 死信消息的消息ID与原始消息的消息ID相同。

执行效果如图:

四、Demo下载
TestAck.zip

总结:有了上面的知识,我们就可以处理未发送成功的消息。解决方案是在发送消息的程序中使用死信队列;在读取消息的程序中,读取死信队列的死信消息,然后重新处理死信消息。

结尾:示例代码是在本机创建专用队列,可以正常执行。如果在远程计算机中,不能直接使用Create方法创建队列,也不能使用Exsits方法判断队列是否存在,我的做法是在远程计算机中手动创建队列,然后配置队列的读取权限。注意,还要把【消息队列】\【属性】\【服务器安全性】\【禁用未经身份验证的RPC调用】取消。感谢园友【一个人的长征】的提醒。

结束语:关于MSMQ的知识点,感觉有好多要讲,比如队列的访问方式,事务队列的使用,日志队列的使用。如果以后有时间,我计划重新整理本篇,做成一个系列,把每个知识点都讲一讲。好了,就像写程序一样,不可能第一版就做的很完美,需要一个迭代的过程,不断的去重构,不断的去优化。

转载于:https://www.cnblogs.com/cs-js/p/5361342.html

使用VMware桥接模式组建局域网测试MSMQ(二)相关推荐

  1. VMware桥接模式无法连网

    2019独角兽企业重金招聘Python工程师标准>>> #VMware桥接模式无法连网 在VMware上装了个CentOS7,使用桥接模式连网,开始使用的时候没有问题,可以正常上网. ...

  2. VMware桥接模式虚拟机上网问题踩坑

    VMware桥接模式虚拟机上网问题踩坑 文章目录 VMware桥接模式虚拟机上网问题踩坑 1.配置windows端: 2.ubuntu端配置: 3 虚拟机能上网主机不能上网的情况 4.虚拟机走主机代理 ...

  3. VMware桥接模式下虚拟机ping主机不通

    问题: VMware设置为桥接模式,虚拟机ping主机不通,主机ping虚拟机通. 解决: 关闭主机(专用网络.来宾或公用网络)和虚拟机的防火墙.(自己由此解决,关闭了win10的,花了乖乖两个小时) ...

  4. 夜神模拟器开启网络桥接模式共享局域网ip

    局域网搜索设备需要模拟器跟物联网设备处于统一网段.夜神设置桥接模式方式 打开命令行输入ipconfig查看网路配置信息 点击夜神 设置–手机–开启网络桥接模式 填入ip 网关 dns等 保存设置重启夜 ...

  5. vmware 桥接模式设置桥接到无线网卡

    vmware共有三种网络,仅主机Host.NAT和桥接模式. 仅主机Host用于和主机通信的网络.NAT用于网络地址转发上网.桥接模式用于搭建与主机之外的网络的网桥. 在添加桥接模式的网卡后,如果使用 ...

  6. Vmware桥接模式上网

    Vmware中的网络连接 Vmware中的网络组件 虚拟交换机 也被称为虚拟网络,命名为VMnet0.VMnet1.VMnet2等等.一些虚拟交换机默认被映射为特定的网络. Windows的Vmwar ...

  7. VMware桥接模式下主机和和虚机间互相ping不通的处理方法

    在 "编辑"->"虚拟网络编辑器" 里面的vmnet0 桥接模式 里面是自动连接,把他改为真实的物理网卡即可,如下图: 转载于:https://www.c ...

  8. [虚拟机][linux]虚拟机VMware桥接模式无法上网问题

    项目场景: linux centso7.3上vmware12 对应虚拟机发现无法正常上网 问题描述 一台服务器发现有问题.网线插在网口1上,一直ping不通,所以换插网口2上,物理机正常.但是虚拟机出 ...

  9. Win10 下 VMware 桥接模式配置

    环境 宿主机系统 虚拟机系统 VMware版本 第一步 开启宿主机 两个服务 配置主机网络适配器 (需要桥接的网卡) 配置VMware 配置虚拟机 关闭 主机与虚机的防火墙 Linux关闭防火墙 测试 ...

最新文章

  1. 【Dubbo源码阅读系列】之远程服务调用(上)
  2. 一台计算机有64,在同一台计算机上使用带有32位和64位Altium设计软件的数据库元件库...
  3. UI5的货币显示格式的逻辑
  4. PostgreSQL创建数据库报错
  5. 绝地求生信号枪只能在服务器吗,绝地求生信号枪怎么用?信号枪刷新点及用法详解...
  6. 数据结构顺序表基本流程
  7. 超详细步骤 | 如何用小程序 SDK 实现电商评价模
  8. 从零开始学习MXnet(四)计算图和粗细粒度以及自动求导
  9. Linux程序包管理和yum用法
  10. 《软件需求分析》读书笔记NO.4
  11. python中的snip用法_简单说说SNIP
  12. D2007从win7升级到win10下的莫名其妙问题。
  13. CCF A类会议或期刊----近两年对比学习相关论文
  14. 目前使用计算机的内存和外存,简述计算机内存和外存区别及常用外存有哪些
  15. 用python实现淘宝毫秒级秒!! 天猫淘宝的抢购完美实现 而且说实话有很多人需要它。 每次在抢购前的无法提交订单导致很多买家无法购买。 今天我教给大家如何更好快速实现你的购买愿望! 教程如下!请仔
  16. Oracle常用函数(zzl)
  17. MATLAB Support Package Installer无法正常打开的问题
  18. 创造正面影响力的社群网 在Facebook能直接捐款给非营利公益组织
  19. QT--动态人流量监测系统
  20. 【IPv6+燎原系列—第7期】天气渐凉,IPv6+将如何助力天气预报?

热门文章

  1. 【总结+计划】2015一月份总结+2015二月份计划——全栈实践
  2. Socket通信原理探讨(C++为例)
  3. [开源] C语言项目实战 - 虚拟鼠标 - VirtualMouse
  4. php 数字转中文函数 1转一,一个阿拉伯数字转中文数字的函数-PHP教程,PHP函数
  5. 定位城市_北方城市如何利用GPS定位器减轻铲雪工作压力?
  6. numpy找到数组中符合条件的数
  7. Quartus和Modelsim中使用`include包含头文件的对比
  8. qsort七种排序方法
  9. matlab fsolve()函数的使用。
  10. 神经网络的设计与分析之概述