消息队列
在计算机科学中,消息队列和邮箱是用于进程间通信或同一进程内的线程间通信的软件工程组件。他们使用一个队列来传播消息——传递控制或者内容。群体传播系统提供类似的功能。
概述
消息队列提供一个异步通信协议,这意味着该消息的发送者和接收者不需要在同一时间与消息队列进行交互。消息被放入队列保存,直到接收方处理他们。消息队列对于一条消息中传输的数据大小有显示或隐式的限制,这样队列中才能保持良好的的消息数量。
消息队列的很多功能由内部实现:在操作系统或应用程序内部。这种队列的存在只为运行于该系统。
其他实现允许不同的计算机系统之间传递消息,可能会连接多个应用程序和多个操作系统。这些消息队列系统通常提供增强的弹性功能,以确保系统故障时消息不会“丢失”。这种消息队列软件(也被称为面向消息中间件)的商业实现的例子包括IBM的WebSphere MQ(MQ系列)和Oracle高级队列(AQ)。Java标准中的Java消息服务(JMS),有几个专有软件和免费软件实现。
各种实现有专有软件,提供消息队列服务,开源软件,或者是基于硬件。
专有选项拥有最长的历史,包括从一开始的消息队列产品,如IBM的WebSphere MQ(MQ系列 ),还有依赖特定操作系统的,如Microsoft消息队列 。
消息队列服务选项,如StormMQ或IronIO。
有很多开放源码选项的消息中间件系统,包括JBoss Messaging,JORAM,Apache ActiveMQ,Sun Open Message Queue,Apache Qpid,[8] RabbitMQ,Beanstalk’d,Tarantool和HTTPSQS [9]
除了开源系统,基于硬件的消息中间件的存在有供应商如Solace系统 ,Sonoa / Apigee和Tervela通过硅或硅/软件数据通路提供队列。
大多数RTOS鼓励使用消息队列作为主要的IPC或线程间通信机制,如VxWorks和QNX操作系统。导致消息传递与CPU调度紧密集成的主要原因是RTOS实时应用程序的可用性。早期的商用的RTOS例子鼓励消息队列基于线程间通信,包括VRTX和pSOS +,可追溯至20世纪80年代初。
使用
在典型消息队列实现中,系统管理员安装配置现成的消息队列软件(队列管理器或中介),并定义一个命名的消息队列。或者注册一个消息队列服务 。
然后,应用程序注册一个软件例程,来“监听”放入队列的消息。
后续的应用程序可以连接到队列并转移其中的消息。
队列管理器软件存储消息,直到接收应用程序连接后调用注册的软件例程。然后,接收应用程序以适当的方式处理该消息。
通常有许多选项作为消息传递的精确语义,包括:
- 持久性 – 消息可能被保存在内存中,写入到磁盘,或甚至提交到DBMS,如果可靠性要求表明了更加资源密集型的解决方案。
- 安全策略 – 哪些应用程序可以访问这些消息?
- 消息清理策略 – 队列或消息应当有存活时间
- 消息过滤 – 一些系统支持过滤数据,因此,订阅者只能看到匹配预定义兴趣标准的消息
- 交付策略 – 我们是不是应该保证消息传递至少一次,或不超过一次?
- 路由策略 – 在一个有许多队列服务器的系统中,哪些服务器应该收到一条消息或一队列的消息?
- 批量策略 – 是否立即将消息传送?还是说系统应该稍等,并尝试一次传递多条消息?
- 排队标准 – 什么时候应当考虑消息“入队”?什么时候队列有了?或者,何时它被转发到至少一个远程队列?或所有队列?
- 已收通知 – 发布者可能需要知道,何时部分或全部订阅者收到了消息。
这些因素都是要考虑的,会显著影响到传输语义,系统的可靠性,系统效率。
标准和协议
从历史来看,消息队列使用了专有的,封闭的协议,以约束不同的操作系统或编程语言在异构环境中交互的能力。
让消息队列更加广泛认知的早期尝试是Sun Microsystem的JMS规范,它提供了仅供Java的客户端API。允许Java开发人员切换消息队列提供者,类似开发人员使用SQL数据库的方式。在实践中,多样化的消息队列技术和方案,并不总是像应有的那般实用。
最近,已经出现了三个标准,使得消息队列开放而广泛:
- 高级消息队列协议
- MQTT
- 面向流文本的消息传递协议
这些全都处于标准化和采纳的不同阶段。他们运转在HTTP的同一层次。
一些专有实现,也使用HTTP来提供消息队列,如Amazon的SQS。
这是因为它总能使用请求-响应语义经由同步协议来分层异步行为(这正是消息队列需要的)。然而这种情况下,这种实现受到底层协议限制,而且可能无法给传递的消息提供必须的完整保真度或设置选项。
同步与异步
许多同步操作的通信协议更加众所周知。HTTP协议 – 用于万维网和Web服务 – 提供了一个明显的例子,用户发送一个网页请求,然后等待答复。
然而,存在这样的情况,此时同步的行为是不恰当的。例如,AJAX( 异步JavaScript和XML)可用于异步发送文本或XML消息,来用更多的相关信息更新一个网页的一部分。谷歌在他的谷歌建议(自动填充)中使用了这种途径,搜索功能将用户输入的部分查询发送到谷歌的服务器,并返回一个列表,包含用户会录入的可能的完整查询。这个列表是在用户录入时异步更新的。
其他异步的例子存在于事件通知系统和发布/订阅系统。
- 一个应用程序可能需要通知别人事件发生了,但并不需要等待响应。
- 在发布/订阅系统中,应用程序“发布”信息,任意数量的客户端阅读。
在上面的例子中,让信息发送者等待是不合理的,例如,如果其中一个接收方已崩溃。
应用程序不必仅作同步或异步 。交互的应用程序可能需要立即回应部分请求(如告诉客户,销售请求已被接受,正在处理库存调货预约),但是也许队列中的其他部分(如完成费用计算,将数据转发到中心记账系统,还有调用各种其它服务)会过一会才完成。
在这些情况下,用一个子系统进行消息排队(或可选择广播消息系统)可有助于提高整体系统的行为。