Queue(队列),这个词在《数据结构》的课程中出现过,即先进先出的一中数据结构,形象例子就是简单的铁路隧道和排队机;和Queue对应的就是stack(栈),Stack是一种先进后出的数据结构;如果看中文书,还有一个名词用于混,就是heap(堆),这个也很形象,进出是没有顺序的,就像煤堆。
在计算机科学中,Message Queue(MQ),就是按顺序传递消息的一种技术。
MQ一般都做为企业级IT应用的中间件存在,有很多企业是作为标准IT基础结构存在的。在市面上常见的MQ中间件有IBM websphere message queue service,Oracle Advanced Queuing,Microsoft Message Queue(MSMQ),Apache ActiveMQ等,其中apache ActiveMQ是基于apache协议的,和tomcat一样,你可以在项目中免费使用,MSMQ是Windows的组件,默认是不被安装的,可以在“添加/删除组件”中安装MSMQ(不同版本的Windows对应的MSMQ版本是不同的,XP/2003是3.0,Vista是4.0)。
MQ一般都具有这几个属性,
-
异步处理;即接收和发送方可以在不同的线程、进程或机器上,发送成功的同时,也不需要接收方立即接收;
-
按消息发送的顺序处理消息(这基本就是废话,因为本身就是Queue )
-
事物性的处理发送和接收消息;多个消息的发送和接收可以做在一个事物中,保证同时成功或同时失败;你也可以将MQ 操作和数据库操作做在一个事物中,来处理一些特定的场景;
-
保证消息的传递;当消息发送成功时,你就可以确定接收方一定能接收到;MQ 会使用某种技术(文件系统、数据库)将消息保存起来;
-
消息的路由;可以按某种规则,将队列中的消息自动的发送到不同的其他队列中;
-
安全;使用多种手段进行权限认证,即程序是否有权限将消息插入到特定的队列中;
-
接收方离线,在使用MQ 的集成项目中,允许消息的接收系统离线,MQ 会保存接收系统离线时发送系统发送的消息,当接收系统上线时,再发送消息给接收系统进行处理。这样可以使多个系统互相隔离,避免了一个系统崩溃,就造成整个流程都崩溃的情况。当然,我们必须保证MQ 服务是在线的,我们可以使用高可靠性应用和负载均衡等技术,缩短MQ 服务的离线时间。
-
异常处理的隔离,由于是异步处理,如果接收方发现发送方发送的消息是有错误的,就可以返回一个消息,交发送方处理,此时,发送方可以使用另一个服务来专门处理异常。
-
消息可以是多种形式的;比如二进制,字符串,XML 等等,发送时,我们需要将数据变成合适的形式;
此外,基本中每种MQ都有其独特的功能,在使用时可以参考对应的用户手册。
MQ使用的主要场景就是异步处理。下面举几个常见的例子。
长耗时的报表,这个在程序中经常遇见,处理海量数据时,可能生成一个报表需要5分中或是更长的时间,客户不能在线实时等待,报表处理比较耗费资源,不能同时处理很多请求,甚至同时只允许处理一个,这时就可以使用MQ。客户端将报表请求和一些必要的报表条件放到Queue中,报表由另一个服务一个一个的处理,处理好后再给用户发一个消息(MSN消息,或mail等)用户再在浏览器或其他报表浏览器中查看报表。
在线商店,在客户下订单的过程后,系统只需做减库存、记录收货人信息和必要的日志,其他的必须配送处理、交易统计等其他处理可以不同时完成,这时就可以将后续处理消息放入Queue中,让另一台(组)服务器去处理,这样可以加快下订单的过程,提高客户的体验;
应用集成,其实和在线商店的情形差不多,系统A处理完毕后,就发送消息给系统B,此时,系统A并不需要等到系统B的处理结果。比如一个货物可能由多个物流服务提供商合作送到客户那里(工厂到码头用一个物流提供商,海上运输用另一个,到另一个码头后由本地物流商送到客户手中),第一个物流商A发送信息给第二个物流商B,物流商A的系统只要确认物流商B的系统已经接收到消息就可以了,并不需要等待处理结果。
系统间的消息通知,系统A处理完成后,将处理后的数据放到某的地方(网络文件服务器、数据库或其他地方),然后发送一个消息通知系统B,系统B收到消息后开始后续的处理;此时系统B并不需要轮询文件系统或数据,可以提高系统的性能
在Java中处理Message Queue。在java中,主要使用JMS(Java Message Service)来处理MQ。JMS是J2EE的重要组成部分。可以参考http://java.sun.com/products/jms/overview.html 。 在J2EE中定义有Message Driven Bean(消息驱动Bean)来进行接收消息后的处理。
在.NET应用中,可以使用System.Messaging空间来处理MSMQ,对于其他的MQ的使用,需要使用对应中间件的.NET API。apache ActiveMQ的子项目NMS提供了ActiveMQ和MSMQ的统一操作方式。
使用MQ还可以得到一个易测试的好处。原来两个系统互相调用时,调试系统A就需要启动系统B,否则A是无法运行的,如果A和B之间使用了MQ连接,测试A时就不需要启动B了,我们只验证A发送给B的消息是正确的就可以了。