AMQ 是符合J2EE™规范的消息服务器,同时针对企业级消息应用做了功能的扩充,提供了诸如消息队列集群和分层次主题命名及多主题订阅。
企业消息传递框架被设计用于使得一个或多个应用能够克服各种障碍进行通信。常见的屏障包括:异步通信的需求,多个应用获取同一条消息(多重传输)的需求,大多数系统都彼此异构,以及网络故障等。
面向消息的中间件系统用来为不同类型的系统提供消息通道。 AMQ 为应用提供了一种公共的、可靠的方式,使这些应用能够轻松地创建、交换和处理消息,而无需考虑消息传递客户机的实现细节。消息被发送到服务器目的地。消息传递客户机只需简单地声明对某个特定的目的地感兴趣,然后通过那个目的地与消息传递服务器进行交互。
消息只是一个字节流(这个字节流可以是一个XML 文档、一个序列化的Java 对象(只是针对Java客户端有此特性)、一个文本字符串或甚至是一条空消息)。对消息的解释留给应用程序来做; AMQ 基础结构不对消息施加任何语义和结构限制。消息存储在队列里, AMQ 服务器允许您将消息加入到队列以及从队列中取走消息。
从概念上来讲,这与现实生活中真实邮件的传递方式没什么不同。消息的发送方只负责使用正确的包装,提供正确的地址,并附上适当的邮资。邮局(这里是一个 AMQ 系统)处理与消息安全和可靠传递相关的所有问题,客户不用关心出现在他们面前的任何障碍(机器故障,天气恶劣,等等)。
在一个 AMQ 系统中,客户机之间的耦合性比较弱,这允许它们不必真正地全天“在线”便能维持服务的最佳质量。如果能够去掉应用一直处于可用状态这一需求,那么维护和伸缩性将变得更加简单。可以在一天中的任何时候将应用离线,更新应用,或者作为例行的维护工作刷新应用,而不必担心会影响服务的质量。
AMQ 不仅为信息传送提供必要的基础结构,而且它还能处理客户要求的、与服务质量、安全性、可靠性和性能有关的大部分基础结构问题。
JMS 是J2EE 规范中提出的消息中间件服务(Java Message Service™)规范,提供应用程序间异步或同步的消息传递和管理服务, AMQ 中包含了高效、可靠、安全的消息服务。 AMQ 中的消息服务接口遵循JMS API规范。提高了企业应用中各组件的可移植性、松耦合性,同时使组件间的消息传递更加高效、可靠和安全;为分布式企业应用异步交换关键业务数据和事件处理提供了可靠而灵活的服务。
Computer A,B,C 为提供消息服务的 AMQ 服务器,每一个 AMQ 服务器称为一个Router,他们之间的连接被称为Connector,客户端进行消息发送时直接与Computer A 连接,客户端要把消息传送到Computer B 的队列时,只需指明接收消息的主机名和队列名,然后发送消息即可,Computer A 中的消息服务将会查找配置文件中的设置,如从A 到B间有无通路连通,假如它们之间有通路连接,消息服务就会寻找这些通路中最短的路径发送消息到指定服务器(Computer B) 的指定队列,假如A 到B 间无有效连接,消息将被保存在某一连通的服务器上,待有有效通路之后再发送消息。
消息队列听起来很象简单的链表。从其最简单形式来说,的确是这样的,但是 AMQ 服务器通过将一些功能特性封装进这一链表管理而增强了其功能, AMQ 具有以下特性:
采用Java语言开发,完全实现行业标准的JMS 1.1及JNDI规范,提供安全、可靠、高效的消息传输。
支持多种操作系统和硬件平台,能够在多种运行平台无缝地进行移植。
提供C、C++、.Net等其它多种语言的调用接口。
可与Apusic Application Server之间进行无缝互操作,构筑企业服务总线的基础。
支持行业标准的安全加密算法,保证消息传输的安全性。
队列、主题权限控制,控制谁可以向队列中写以及谁可以从队列中读的安全性。
灵活的消息存储机制,消息可存放在文件、内嵌的Berkely DB或通过JDBC存放到关系数据库中。
支持远程队列,可在本地直接获取远程队列上的消息。
支持消息拆分,可将大消息拆分为小消息发送,能够传输超过几十G的消息。
支持消息传输时的断点续传
智能路由技术,消息传输时会自动寻找一条最优路径进行传输。
提供智能的消息压缩算法,最大限度的减小网络的负担,提高消息传输时的效率和服务器的吞吐量。
支持集群,能够承受大并发,避免单点故障,提供7*24小时不间断服务。
支持集群队列零管理,只需要将一个本地队列发布出去就可以被集群中的任何节点使用。
集群环境中的消息智能分发技术(抗抢夺算法)以及工作负载均衡和通信故障切换功能。
分层次主题命名及多主题订阅,可以完成在单主题订阅模式下无法完成的特性。
在文件传输工具和客户端API级别提供无限制、断点续传的文件传输功能、使企业能够提升现有FTP架构,以确保在 AMQ 上进行可靠,安全的文件传输。
提供基于Eclipse技术的全新的MQ集中式管理与监控工具,能够在单节点上对整个MQ网络上的所有节点进行管理与配置、监控整个MQ网络目前的拓扑结构、连接状态,以及整个MQ网络上任何一个节点所发生的事件,让您对您的网络一目了然,实时掌握整个系统的运行状况。
事务支持,入队和出队操作都具有事务特性:原子性、一致性、隔离性以及可持久性。
分布式事务支持,队列操作可以同其它资源(如 数据库)一起参加分布式事务。
该节主要描述和 AMQ 相关的一些技术概念。
消息包括消息头,消息属性,消息体三部分。
消息头:所有的消息使用相同的消息头属性集合,主要用来标示消息ID,路由信息等
消息属性:对消息头信息的补充,因为消息头是固定的一些属性,而消息属性可以自己定义的。
消息体: AMQ 支持主要的一些消息类型,例如:StreamMessage, MapMessage, TextMessage, ObjectMessage, BytesMessage。其中ObjectMessage是针对Java的特殊格式。
| 消息类型 | 消息体 |
|---|---|
| TextMessage | A java.lang.String object (for example, the contents of an Extensible Markup Language file). |
| MapMessage | A set of name-value pairs, with names as String objects and values as primitive types in the Java programming language. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined. |
| BytesMessage | A stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. |
| StreamMessage | A stream of primitive values in the Java programming language, filled and read sequentially. |
| ObjectMessage | A Serializable object in the Java programming language. |
| Message | Nothing. Composed of header fields and properties only. This message type is useful when a message body is not required. |
PTP(Point-to-Point)模型是基于队列的,发送方发消息到队列,接收方从队列接收消息,队列的存在使得消息的异步传输成为可能。和邮件系统中的邮箱一样,队列可以包含各种消息,AMQ 提供了工具用于管理队列的创建、删除等维护性工作。PTP 模型定义了客户端如何向队列发送消息,从队列接收消息,浏览队列中的消息等功能。
下面描述 PTP 模型中的主要概念和对象:
| 名称 | 描述 |
|---|---|
| Queue | 由 AMQ 管理,队列由队列名识别,客户端可以通过 AMQ 提供的客户端接口用队列名得到一个队列对象。 |
| TemporaryQueue | 由QueueConnection 创建,而且只能由创建它的QueueConnection 使用。 |
| QueueConnectionFactory | 客户端用QueueConnectionFactory 创建QueueConnection 对象。 |
| QueueConnection | 一个到 AMQ 的连接,客户端可以用QueueConnection 创建 QueueSession 来发送和接收消息。 |
| QueueSession | 提供一些方法创建 QueueReceiver 、QueueSender、QueueBrowser 和 TemporaryQueue。如果在 QueueSession 关闭时,有一些消息已经被收到,但还没有被签收(acknowledged),那么,当接收者下次连接到相同的队列时,这些消息还会被再次接收。 |
| QueueReceiver | 客户端用QueueReceiver 接收队列中的消息,如果用户在QueueReceiver 中设定了消息选择条件,那么不符合条件的消息会留在队列中,不会被接收到。 |
| QueueSender | 客户端用QueueSender 发送消息到队列。 |
| QueueBrowser | 客户端可以使用QueueBrowser 浏览队列中的消息,但不会收走消息。 |
| QueueRequestor | AMQ 的客户端接口提供了QueueRequestor 类,用于简化消息的收发过程。QueueRequestor 的构造函数有两个参数:QueueSession 和queue,QueueRequestor 通过创建一个临时队列来完成最终的收发消息请求。 |
| 可靠性(Reliability) | 队列可以长久地保存消息直到接收者收到消息。接收者不需要因为担心消息会丢失而时刻和队列保持激活的连接状态,充分体现了异步传输模式的优势。 |
AMQ 的 Pub/Sub 模型定义了如何向一个内容节点发布和订阅消息,这些节点被称作主题(topic)。
主题可以被认为是消息的传输中介,发布者(publisher)发布消息到主题,订阅者(subscribe)从主题订阅消息。主题使得消息订阅者和消息发布者保持互相独立,不需要接触即可保证消息的传送。
下面描述 Pub/Sub 模型中的主要概念和对象:
| 名称 | 描述 |
|---|---|
| 订阅(subscription) | 消息订阅分为非持久订阅(non-durable subscription)和持久订阅(durable subscrip-tion),非持久订阅只有当客户端处于激活状态,也就是和 AMQ 保持连接的状态时,才能收到发送到某个主题的消息,而当客户端处于离线状态的时候,这个时间段发到主题的消息将会丢失,永远不会收到。持久订阅时,客户端向 AMQ 注册一个识别自己身份的ID,当这个客户端处于离线时,AMQ 会为这个ID 保存所有发送到主题的消息,当客户再次连接到 AMQ 时,会根据自己的ID 得到所有当自己处于离线时发送到主题的消息。 |
| Topic | 主题由 AMQ 管理,主题由主题名识别,客户端可以通过 AMQ 提供的客户端接口用主题名得到一个主题对象。 |
| TemporaryTopic | 临时主题由TopicConnection 创建,而且只能由创建它的TopicConnection 使用。临时主题不能提供持久订阅功能。 |
| TopicConnectionFactory | 客户端用TopicConnectionFactory 创建TopicConnection 对象。 |
| TopicConnection | TopicConnection 是一个到 AMQ 的连接,客户端可以用TopicConnection创建TopicSession 来发布和订阅消息。 |
| TopicSession | TopicSession 提供一些方法创建 TopicPublisher、TopicSubscriber、TemporaryTopic 。它还提供 unsubscribe 方法取消对某个主题的持久订阅。 |
| TopicPublisher | 客户端用TopicPublisher 发布消息到主题。 |
| TopicSubscriber | 客户端用TopicSubscriber 接收发布到主题上的消息。可以在TopicSubscriber 中设置消息过滤功能,这样,不符合要求的消息不会被接收。 |
| Durable TopicSubscriber | 如果一个客户端需要持久订阅消息,可以使用Durable TopicSubscriber,TopSession 提供一个方法createDurableSubscriber创建Durable TopicSubscriber 对象。 |
| 恢复和重新派送(Recovery and Redelivery) | 非持久订阅状态下,不能恢复或重新派送一个未签收的消息。只有持久订阅才能恢复或重新派送一个未签收的消息。 |
| TopicRequestor | AMQ 提供TopicRequestor 类简化消息的收发过程。TopicRequestor 的构造函数有两个参数:TopicSession 和topic。TopicRequestor 通过创建一个临时主题来完成最终的发布和接收消息请求。 |
| 可靠性(Reliability) | 当所有的消息必须被接收,则用持久订阅模式。当丢失消息能够被容忍,则用非持久订阅模。 |
消息的同步接收
同步接收是指客户端主动去接收消息,AMQ 的客户端可以采用MessageConsumer的receive方法去接收下一个消息。
消息的异步接收
异步接收是指当消息到达时,主动通知客户端。AMQ 的 客户端可以通过注册一个实现了 MessageListener 接口的对象到 MessageConsumer 中,这样,每当消息到达时,AMQ 会调用 MessageListener 中的 onMessage 方法,通知客户端。
非持久化方式
非持久化方式是指消息不持久化到可靠的存储设备里,这样带来的是效率提高,但是如果消息服务器崩溃或失败的时候存在消息丢失的可能性。
持久化方式
持久化方式表示消息服务器提供了机制保证消息在发生任何异常的情况下不会丢失。
AUTO_ACKNOWLEDGE 模式
在 AUTO_ACKNOWLEDGE 模式下,会话自动确认客户端收到的每条消息。此外,会话线程会阻塞,等待代理确认它已处理了每个已使用消息的客户端确认。而该确认称为“代理确认”。对于由消息侦听器执行的异步消息接收,消息在 onmessage() 方法返回后被确认。对于同步消息接收,消息恰好在 receive() 方法返回前被确认。在这种情况下,可能只对消息进行部分处理;如果在使用消息前系统发生了故障,则消息就会丢失。为提高可靠性,可以使用 CLIENT_ACKNOWLEDGE 模式或事务会话来确保系统发生故障时消息不会丢失。
CLIENT_ACKNOWLEDGE 模式
CLIENT_ACKNOWLEDGE 模式授予客户端最高的控制权限。在此模式下,客户端在使用一条或多条消息后显式对其进行确认。确认发生在客户机调用消息对象的 acknowledge() 方法时,调用该方法会导致会话确认自上次调用该方法以来它使用的所有消息(其中可能包括会话中许多不同的消息侦听器以异步方式使用的消息,与使用这些消息的顺序无关)。
此外,会话线程会阻塞,等待为已使用的一批消息返回代理确认,它确定代理已对客户机确认进行了处理。
由于通常按批次发送客户机确认和代理确认(而非逐个发送),因此,与 AUTO_ACKNOWLEDGE 模式相比,CLIENT_ACKNOWLEDGE 模式通常节省连接带宽,并减少代理确认的开销。当然,如果在此模式下客户机对每条消息逐一进行确认,则不会按批次发送确认,而是逐一地发送确认。
DUPS_OK_ACKNOWLEDGE 模式
在 DUPS_OK_ACKNOWLEDGE 模式下,会话在使用了十条消息后进行确认,目前无法对该值进行配置。与 AUTO_ACKNOWLEDGE 或 CLIENT_ACKNOWLEDGE 模式不同的是,会话线程不会阻塞等待代理确认,因为在 DUPS_OK_ACKNOWLEDGE 模式下不请求任何代理确认。
这意味着,无法保证只对消息传送和使用一次。一般来说,不会非常频繁地重新传送消息;这种情况只会在发生故障(代理未收到它所传送的消息的客户机确认)时出现。如果客户机对重复传送并不在意,则应使用 DUPS_OK_ACKNOWLEDGE 模式。
由于客户机确认按批次发送且客户机线程不会阻塞,因此消息吞吐量通常远高于其他模式。
多个提供消息服务的 AMQ 可以组成一个虚拟的MQ网络,每个提供消息服务的 AMQ 可被视为一个MQ网络中的节点,而节点之间的连接则通过声明消息路由提供。只要用户连接到MQ网络中任何一个节点,即可向网络中的其他任意节点发送消息。
为提供消息服务的可靠性,和MQ网络中消息的暂时存储, AMQ 使用了一个可靠的消息存储机制。
AMQ 消息路由与存储配置的,存在于 AMQ 目录下config子目录中mq.conf文件。mq.conf 文件中可对消息服务的消息存储目录和消息路由进行配置。
AMQ 现在支持消息队列集群(Message Queue Clustering)。所谓消息队列集群是指在多个 AMQ 之间建立路由连接,从而组成一个消息路由网络。在网络中任何一个结点上定义的集群消息队列都将被其他结点所共享,通过任何一个结点向一个集群队列发送消息都是等效的,对客户来说无法察觉是否正在使用集群,集群中网络拓扑结构发生变化对客户也没有任何影响。
当路由结点与其他结点建立连接时通过发布自身定义的集群队列从而使集群队列获得共享,无须系统管理员干预,大大减少了路由网络的维护量。使用集群还可以提高系统的可用性,路由网络中单个结点发生故障停机或部分网络无法连通时并不影响集群队列的使用,同时在发送消息时根据各结点的负荷情况对负载进行分配,从而使结点处理能力和网络带宽被充分利用。
分层次主题命名是 AMQ 提供一种主题(Topic)分组定义的方法,使主题更便于管理和使用。除此之外,AMQ 还提供了使用模式匹配的方式同时订阅多个主题,从而可以完成在单主题订阅模式下无法完成的特性。
当对一个主题命名时也同时定义了这个主题所处的层次结构。在一个不分层的命名系统中,所有的名字都是孤立的,彼此之间没有任何关系,当主题增加时会带来很大的管理负担。而在一个分层次命名系统中名字之间具有一定的上下级关系,从而可以对层次结构中的一组结点进行管理并明确指明结点之间的关系。
AMQ 中使用'.'分隔符来指明这种上下级关系,类似于文件系统中使用'/'分隔符来区分上下级目录。通常只需要定义叶结点,中间结点系统将自动建立。
向主题发布消息时可以发布到层次结构中的任何一个结点上,而在订阅消息时可以使用模式匹配的方式同时订阅多个主题,这些主题可以是层次结构中的某个分支,也可以是一些并没有命名关系的主题。模式匹配所使用的语法很简单但很强大,可以灵活地选择需要的主题。