MSMQ消息队列 用法

引言

接下来的三篇文章是讨论有关企业分布式开发的文章,这三篇文章筹划了很长时间,文章的技术并不算新,但是文章中使用到的技术都是经过笔者研究实践后总结的,正所谓站在巨人的肩膀上,笔者并不是巨人,但也希望这几篇文章能够帮助初涉企业分布式开发的一些童鞋。
        三篇文章将会从MessageQueue、Windows Services和WCF着手来讨论企业分布式的开发,MQ是一种消息中间件技术,该篇文章将会详细讨论。Windows Services在分布式开发中同样起着重要的作用,将会在下篇文章中详细讨论,最后是使用MQ、WS并结合WCF做一个分布式的Demo来演示分布式的架构。在敲定写这几篇文章前还有一个重要的内容--ESB(Enterprise Service Bus,企业服务总线),它是传统中间件技术与XML、Web服务等技术结合的产物,也就是集合了MQ和WS为一体的一种框架,但还没有做详细的研究所以这三篇文章就没有包括ESB,等到有充足的时间了然后再去详细的研究吧。
        

一、 论新技术的学习

在使用到新技术时往往首先需要学习它,然后在项目中应用,这里说到了学习那么就来讨论下技术学习的方法,也是笔者对新技术学习的一种总结。
         对于做旧了开发的人员来说在学习新技术时往往会比年轻的开发人员较快,这个问题有没有想过?其实这个问题的答案相当的简单,在学习新技术时对于不同的人都是站在同一个起跑线的,只不过对于有经验的开发人员来说,在使用新技术时学习的并不是它是什么东西,而是学习的如何使用它。这种不同的思想观点就决定了谁会掌握的更快,可以这么理解,开发是一个世界,刚踏入编程界的人来说就像是刚出生的一个婴儿,这时候他们是要去认知这个世界,于是就会问很多问题,诸如:面向对象是什么东西,为什么要这样编写,最后把自己陷入到一个个泥潭中。但是对于经验丰富的开发人员来说,他要认知不是这个世界,在开发中可以说已经是成年人,在学习新技术时就不会问很愚蠢的问题,而是会想这个东西也是面向对象的,那么可以把方法封装到一个基类中,子类继承父类的方法,然后重写来实现多态,所以这时候经验就决定了学习新技术时的快慢。
         这就类似于生活中的幼儿和成年人在学习开电动车时的场景,想要幼儿使用电动车就会很困难,因为最简单的脚踏车都没有骑过,你让他学习电动车,这不是作死的节奏吗。但是成年人就不同了,成年人骑脚踏车相当的熟练,在换电动车的时候就会想这个和脚踏车是一样的,而且可以不用每次脚踩,真是好用。这两种思维方式就决定了幼儿在使用电动车时需要几天的事件才能学会,但是成年人刚看到就能够使用。
          学习新技术也是类似,新技术也是只是一种新的实现方式,可能给它加上了一个电动的开关,做一个开关然后使用它里面的功能自个儿运行就可以了,实际的内容还是没有改变都是0和1的集合体。

二、MQ

上文讨论了学习的方法,接下来将会进入文章的正题,讨论有关MQ的基本使用方法。首先来对MQ的基本内容进行分类,这里从静态和行为角度将MQ的内容分为两大类,其中的静态角度是指MQ所包含的类别以及在系统消息队列中的类型,行为角度是指MQ在通信方面的类型,具体分类如下图:
MSMQ消息队列 用法
        MQ是一种通信的机制,因为是一种中间件技术,所以它能够支持多种类型的语言开发,同时也是跨平台的通信机制,也就是说MQ支持将信息转化为XML或者JSon等类型的数据存储到消息队列中,然后可以使用不同的语言来处理消息队列中的消息,这样就很容易的做到了信息的通信,同时也为信息的通信起到了缓冲的作用,经常会在金融项目中使用这种通信机制。
 

2.1 理论积淀

2.1.1 静态

消息队列是和网络相关联的,所以根据网络的不同划分为公共队列、专用队列,其中公共队列是公布到整个网络中,在整个网络中所有站点公开,相对的就是专用队列,专用队列只能由知道队列完整路径名或标签的应用程序访问。另外根据接收消息的操作不同把消息队列划分为管理队列和响应队列,管理队列是指在整个消息线路中所有已经发送和接收的消息;响应队列是指目标程序接收和回应消息。它们在消息队列中的类型,可以使用下图来进行区分。

MSMQ消息队列 用法

另外对于系统生成的队列这里不再详细的描述,可以上网查看一些文章。

2.1.2 行为

在行为方面从队列的通信和消息处理两个大的方面把MQ分为两大类,其中MQ的队列通信分为同步和异步两种类型,同步消息是指请求的发送方执行其他任务前,必须等待来自预定接收方的响应,具体等待的时间取决于接收方处理响应的时间。和同步相对应的是异步消息,发送方不会等待接收方的任何回应即可继续其它的操作。

        另外在消息队列交互方面,消息的交互同时也有数据完整性、数据一致性、稳定性等类型的,具体分为稳定性、消息优先级、脱机能力、事务性和安全性等。

2.2 MQ 详解

理论部分已经积累的很多了,接下来我们从实际的代码实例中来分析MQ的使用方法,另外在使用MQ前首先应该要安装MQ才可以,这样在本机的服务器上才会有MQ的管理器,做消息处理的时候可以查看消息的具体内容。

2.2.1 MQ安装

打开Control Panel-“Add/Remove Programs” – “Add/Remove Windows Components”步骤安装MSMQ。

MSMQ可以安装为工作组模式或域模式。如果安装程序没有找到一台运行提供目录服务的消息队列的服务器,则只可以安装为工作组模式,此计算机上的“消息队列”只支持创建专用队列和创建与其他运行“消息队列”的计算机的直接连接。

2.2.2 配置MSMQ

打开Computer Management – Message Queuing,在Private Queues下创建MSMQDemo队列

2.2.3 MQ Demo

在.NET中微软对MQ做了封装,把MQ有关的信息封装到了MessageQueue类中,在开发的时候可以直接引用该类,对队列中的消息做操作。
        在操作消息前首先要为消息指定存储的队列,所以在创建消息时首先要在服务器上创建一个队列,然后为MessageQueue指定消息队列的路径。具体MQ类的方法和属性如下导图:
MSMQ消息队列 用法

        MQ类的主要使用方法已经在上面的导图中列出,接下来分析类中的主要方法和属性。
        (1)在Method中分为队列管理和消息管理两类方法,其中的队列管理的方法很简单,通过调用方法就能够创建和删除队列。另外就是消息管理的方法,其中的方法分为同步和异步两种类型,可以根据实际的需求来确定使用的类型。
        (2)在Property中主要用到的主要是Path和Label属性,其中的Path指定消息的队列地址,Label能设置或获取队列描述信息。

接下来演示发送数据和接收数据代码的编写方法,下面的示例中使用的是私有的队列类型来演示的操作。首先从发送数据开始,在发送数据时首先要创建我们的MQ,然后根据MQ的地址创建相应的队列,调用队列的send方法将数据信息发送到队列中,如下代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Messaging;
  6. using System.Runtime.CompilerServices;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Xml;
  10. using System.Xml.Serialization;
  11. using System.Runtime.Serialization.Formatters.Binary;
  12. namespace MsMQTest
  13. {
  14. class Program
  15. {
  16. static void Main(string[] args)
  17. {
  18. //declare the MQ Path
  19. string ekQ= ".\\Private$\\EKTestQueue";
  20. //create the MQ if the MQ is not exist
  21. if (!MessageQueue.Exists(ekQ))
  22. MessageQueue.Create(ekQ);
  23. //create a new queue
  24. var queue = new MessageQueue(ekQ);
  25. for (int i = 0; i < 2; i++)
  26. {
  27. //create the model that want to send
  28. Test test=new Test();
  29. test.Name = "fdsfd";
  30. test.Sex = "cvx";
  31. //serialize the model
  32. string str = Program.xmlSerial(test);
  33. //send the model data to queue
  34. queue.Send("Test" + str);
  35. Console.WriteLine("Message sent {0} \n--------------", "Test" +str);
  36. }
  37. Console.Read();
  38. // MessageQueue.Delete(ekQ);
  39. }
  40. public static string xmlSerial<T>(T serializeClass)
  41. {
  42. string xmlString = string.Empty;
  43. XmlWriterSettings settings = new XmlWriterSettings();
  44. XmlSerializer serializer = new XmlSerializer(typeof(T));
  45. StringBuilder xmlStringBuilder = new StringBuilder();
  46. using (XmlWriter writer = XmlWriter.Create(xmlStringBuilder))
  47. {
  48. serializer.Serialize(writer, serializeClass);
  49. xmlString = xmlStringBuilder.ToString();
  50. }
  51. return xmlString;
  52. }
  53. }
  54. public class Test
  55. {
  56. public string Name { get; set; }
  57. public string Sex { get; set; }
  58. }
  59. }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Messaging;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary; namespace MsMQTest
{
class Program
{
static void Main(string[] args)
{
//declare the MQ Path
string ekQ= ".\\Private$\\EKTestQueue"; //create the MQ if the MQ is not exist
if (!MessageQueue.Exists(ekQ))
MessageQueue.Create(ekQ); //create a new queue
var queue = new MessageQueue(ekQ); for (int i = 0; i < 2; i++)
{
//create the model that want to send
Test test=new Test();
test.Name = "fdsfd";
test.Sex = "cvx";
//serialize the model
string str = Program.xmlSerial(test);
//send the model data to queue
queue.Send("Test" + str);
Console.WriteLine("Message sent {0} \n--------------", "Test" +str);
} Console.Read(); // MessageQueue.Delete(ekQ);
} public static string xmlSerial<T>(T serializeClass)
{
string xmlString = string.Empty;
XmlWriterSettings settings = new XmlWriterSettings();
XmlSerializer serializer = new XmlSerializer(typeof(T));
StringBuilder xmlStringBuilder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(xmlStringBuilder))
{
serializer.Serialize(writer, serializeClass);
xmlString = xmlStringBuilder.ToString();
} return xmlString;
}
} public class Test
{
public string Name { get; set; }
public string Sex { get; set; }
}
}

对应的生成结果如下图:

MSMQ消息队列 用法

运行上面的代码后MQ将会把消息发送到相应的队列中,这里采用的是专有队列所以会将消息发送到本地的队列中,查看消息如下图所示:

  MSMQ消息队列 用法

运行上面的代码后会把消息发送到相应的消息队列中,这样在消息的发送方和调用方之间就构建了一个相互松耦合的桥梁,它就是消息队列,接下来演示如何接收消息队列。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Messaging;
  5. using System.Text;
  6. using System.Threading;
  7. namespace MsqueueReaderTest
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. string ekQ = ".\\Private$\\EKTestQueue";
  14. using (var queue = new MessageQueue(ekQ))
  15. {
  16. queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
  17. var exist = false;
  18. while (!MessageQueue.Exists(ekQ))
  19. {
  20. Console.WriteLine("No existing queue");
  21. }
  22. exist = true;
  23. while (exist)
  24. {
  25. var m = queue.Receive();
  26. Console.WriteLine("Message Received {0} \n--------------",(string)m.Body);
  27. // Thread.Sleep(500);
  28. }
  29. }
  30. }
  31. }
  32. }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading;
namespace MsqueueReaderTest
{
class Program
{
static void Main(string[] args)
{
string ekQ = ".\\Private$\\EKTestQueue"; using (var queue = new MessageQueue(ekQ))
{
queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
var exist = false;
while (!MessageQueue.Exists(ekQ))
{
Console.WriteLine("No existing queue"); }
exist = true;
while (exist)
{
var m = queue.Receive();
Console.WriteLine("Message Received {0} \n--------------",(string)m.Body);
// Thread.Sleep(500);
}
} }
}
}

运行程序后控制台输出结果:

MSMQ消息队列 用法

在上例中我们使用的异步Receive方法,而且该方法会将消息队列中的消息取出并删除,所以在操作完成后消息队列中的消息会为空,所以运行后的队列为下图:

MSMQ消息队列 用法

结语

MQ是一种企业服务的消息中间节技术,这种技术常常伴随着企业服务总线相互使用,构成了企业分布式开发的一部分,如果考虑到消息的发送和传送之间是可以相互不联系的并且需要分布式架构,则可以考虑使用MQ做消息的中间价技术,MQ的功能已经足够开发使用。但是对于分布式开发的技术只了解MQ是远远不足够的,因为在系统中往往会实现消息的自动发送和获取,如果想要实现消息队列的自动操作就不得不说说Windows服务了,下文将会对Windows服务做详细的讨论。

版权声明:本文为博主原创文章,未经博主允许不得转载。

上一篇:剑指offer-面试题14.调整数组顺序使奇数位于偶数的前面


下一篇:mysql聚集索引的优缺点