消息传送中间件使各组件和应用程序可通过生成并使用消息来进行通信。JMS API 定义管理该通信的两种模式或消息传送域:点对点消息传送和发布/订阅消息传送。JMS API 的组织可支持这些模式。基本 JMS 对象包括:用于指定两个域中的消息传送行为的连接、会话、生成方、使用方、目的地和消息。
在点对点域中,消息生成方被称为发送者,而使用方被称为接收者。它们通过被称为队列的目的地来交换消息:发送者生成队列中的消息;而接收者则使用队列中的消息。
图 2–1 显示了点对点域中最简单的消息传送操作。MyQueueSender 向队列目的地 MyQueue1 发送 Msg1。然后, MyQueueReceiver 从 MyQueue1 获得该消息。
图 2–2 显示了一个更为复杂的点对点消息传送图,以说明该域中的可能情况。两个发送者 MyQSender1 和 MyQSender2 使用同一连接向 MyQueue1 发送消息。 MyQSender3 使用另一连接向 MyQueue1 发送消息。在接收端,MyQReceiver1 独占一个连接使用 MyQueue1 中的消息,而 MyQReceiver2 和 MyQReceiver3 共享一个连接以使用 MyQueue1 中的消息。
这个较为复杂的图说明了有关点对点消息传送的其他几点。
多个生成方可向一个队列发送消息。生成方可共享连接或使用不同连接,但它们均可访问同一队列。
多个接收者可以使用一个队列中的多条消息,但每条消息只能由一个接收者使用。所以,Msg1、Msg2 和 Msg3 由不同的接收者使用。(这是 Message Queue 的扩展。)
接收者可共享连接或使用不同连接,但它们均可访问同一队列。(这是 Message Queue 的扩展。)
发送者和接收者之间不存在时间上的相关性:客户端发送一条消息后,无论接收者是否正在运行,都能获取该消息。
可在运行时动态添加和删除发送者和接收者,这样,即可根据需要缩放消息传送系统。
消息在队列中按发送的顺序排列,但使用消息的顺序取决于多种因素,例如消息失效日期、消息优先级以及使用消息时是否使用了选择器。
点对点模型具有许多优势:
由于多个接收者可以使用同一队列中的消息,因此如果消息的接收顺序不重要,则可以对消息的使用进行负载平衡。(这是 Message Queue 的扩展。)
要发送到队列的消息始终保留,即使没有接收者也是如此。
Java 客户端可以使用队列浏览器对象检查队列的内容。然后,它们可以根据通过该检查所获得的信息来使用消息。也就是说,虽然使用模型一般为 FIFO(first in, first out,先进先出),但如果使用者知道要使用哪些消息,即可使用消息选择器来使用未处于队列最前方的消息。管理客户端也可以使用队列浏览器来监视队列的内容。
在发布/订阅域中,消息生成方被称为发布者,而消息使用方则被称为订户。它们通过称为主题的目的地来交换消息:发布者生成主题中的消息;订户则订阅主题并使用主题中的消息。
图 2–3 显示了发布/订阅域中的简单消息传送操作。MyTopicPublisher 向目的地 MyTopic 发布 Msg1。然后,MyTopicSubscriber1 和 MyTopicSubscriber2 均从 MyTopic 接收 Msg1 的副本。
虽然发布/订阅模型不要求多个订户,但图中仍显示了两个订户来强调通过此域可以广播消息。一个主题的所有订户均可获得发布到该主题的任何消息的副本。
长期订户可能处于活动状态,也可能处于非活动状态。代理会为所有活动订户保留消息,但对于非活动订户,则只为那些长期订户保留消息。
图 2–4 显示了更为复杂的发布/订阅消息传送图,以说明该模式提供的可能情况。多个生成方向 Topic1 目的地发布消息。多个订户使用来自 Topic1 目的地的消息。除非订户使用选择器来过滤消息,否则每个订户均可获得发布到所选主题的所有消息。在图 2–4 中,MyTSubscriber2 已过滤掉 Msg2。
这张较为复杂的图说明了有关发布/订阅消息传送的很多其他点。
多个生成方可向一个主题发布消息。生成方可共享连接或使用不同连接,但它们均可访问同一主题。
多个订户可使用一个主题中的消息。订户可检索发布到一个主题中的所有消息,除非它们使用选择器过滤掉消息或消息在使用之前已过期。
订户可共享连接或使用不同连接,但它们均可访问同一主题。
可在运行时动态添加和删除发布者和订户,这样,即可根据需要缩放消息传送系统。
消息按发送的顺序发布到主题,但使用消息的顺序取决于多种因素,例如消息失效日期、消息优先级以及使用消息时是否使用了选择器。
发布者与订户之间存在时间上的相关性:主题订户只能使用在它创建订阅后发布的消息。
JMS API 定义可用于实现点对点域或发布/订阅域的接口和类。这些是表 2–1 的第 2 列和第 3 列中显示的特定于域的 API。JMS API 还定义另外一个统一域,用于通过编程实现常规的消息传送客户端。这类客户端的行为由目的地类型决定,客户端向目的地中生成消息并使用目的地中的消息。如果该目的地是一个队列,则消息传送行为将为点对点模式;如果该目的地是一个主题,则消息传送行为将为发布/订阅模式。
表 2–1 JMS 编程域和对象
基本类型(统一域) |
点对点域 |
发布/订阅域 |
---|---|---|
Destination(队列或主题) |
Queue |
Topic |
ConnectionFactory |
QueueConnectionFactory |
TopicConnectionFactory |
Connection |
QueueConnection |
TopicConnection |
Session |
QueueSession |
TopicSession |
MessageProducer |
QueueSender |
TopicPublisher |
MessageConsumer |
QueueReceiver |
TopicSubscriber |
统一域通过 JMS 版本 1.1 引入。 如果需要遵守早期的 1.02b 规范,则可以使用特定于域的 API。使用特定于域的 API 还能够提供全新编程接口,可以防止出现某些类型的编程错误:例如,为队列目的地创建长期订户。但是,特定于域的 API 的缺点是,不能在同一事务或同一会话中将点对点和发布/订阅操作相结合。如果需要执行该操作,则应选择统一域 API。有关将两种域相结合的示例,请参见请求-回复模式。