16boke - 一路博客

JMS发布/订阅模型

6.1 概述

JMS Pub/Sub模型定义了JMS客户端如何发布消息到基于内容层次的众所周知的节点和如何从节点订阅消息。JMS 将这些节点称为主题(topic)。

在这一节,术语publish和subscribe用于替代前面更常用的术语produce和consume。

注意可以被看作是一个小的消息代理,它收集和分发定位到它的消息。通过依靠主题作为中介,消息发布者和订阅者保持独立。主题随着发布者和订阅者的变化而自动适配。

当代表它们的Java对象存在时,发布者和订阅者是活动的。JMS 也支持可选的永久订阅者,这些订阅者在不活动时也会被记住是存在的。

本章描述Pub/Sub模型的语义。支持Pub/Sub模型的JMS提供商必须支持这里描述的语义。

不管JMS客户端程序使用Pub/Sub域特有的接口还是使用在第4章“JMS公共工具”中描述的公共接口,客户端程序必须被保证有相同的行为。

表6‐1展示了Pub/Sub域特有的接口和JMS的公共接口。公共接口是创建JMS 应用程序的最佳方式,因为它们是独立于域的。

表 6.1. Pub/Sub域接口和JMS公共接口

Pub/Sub域接口JMS最佳的公共接口
TopicConnectionFactory ConnectionFactory
TopicConnection Connection
Topic Destination
TopicSession Session
TopicPublisher MessageProducer
TopicSubscriber MessageConsumer

6.2 Pub/Sub延时

由于在所有的Pub/Sub系统中通常都会有一些延时,订阅者实际看见的消息的时间根据JMS提供商产生新的订阅者和提供商在转发过程中保留消息的时间长度会有很大的不同。

例如,由于新的订阅者传播到整个系统会花费一些时间,因此来自远方发布者的消息可能会被错过。当创建新的订阅者时,它可以接收在创建之间发送的消息,因为提供商可能还没有让订阅者可以获取这些消息。

JMS没有定义在pub/sub提供商调整到新的客户端的间隔期内的语义。JMS语义只应用到达到“稳定状态”的提供商。

6.3 永久订阅

非永久订阅维持着订阅者对象的生命。这意味着客户端将只能看见在订阅者是活动时发布到主题的消息。如果订阅者是不活动的,那么它将错过发布到主题的消息。

订阅者可以以高负荷的成本来使用永久订阅。永久订阅者用一个唯一标识向JMS注册一个永久订阅。使用同一个标识的后续订阅者对象重新使用前一个订阅者使用过的订阅,这个订阅的状态是前一个订阅者留下的。如果永久订阅没有活动的订阅者,则JMS 保留订阅的消息直到它们被订阅接收或到期。

所有的JMS提高商必须能够动态创建和删除永久订阅的JMS应用。另外,某些JMS提供商可以提供管理配置永久订阅的工具。如果永久订阅已经被配置,它可以默默覆盖由客户端指定的订阅。

不活动的永久订阅是一个存在但当前还没有消息消费者向它订阅的永久订阅。

6.4 主题(Topic)管理

某些产品要求主题是静态定义、要与权限控制相关联,等等;其他的甚至没有主题管理的概念。

JMS没有定义创建、管理或删除主题的工具。

一种特殊类型的主题是TemporaryTopic,它用于创建一个对于TopicConnection来说是唯一的Topic。参见节6.6“临时主题(TemporaryTopic)”了解详细信息。

6.5 Topic

Topic对象封装了提供商特有的主题名。它用于在JMS方法中指定主题标识。

许多Pub/Sub提供商将主题组织成层级形式,并提供很多选项来订阅层级的部分主题。JMS对Topic 对象代表什么没有限制。它可能是主题层级的叶子,或者可能是层级的较大部分(用于订阅信息的大类)。

主题的组织和订阅授权都是Pub/Sub应用架构很重要的部分。JMS没有指定如何实现它们的策略。如果应用使用了提供上特有的分组机制,那么它应当记录它。如果应用使用不同的提供商,那么管理员负责构造相等的主题架构和创建相等的Topic对象。

6.6 TemporaryTopic

TemporaryTopic是一个唯一的Topic对象,它为Connection或TopicConnection永久化而创建。它是系统定义的Topic,只能被创建它的Connection 或TopicConnection消费。

根据定义,向一个临时主题创建永久订阅是没有意义的。如果这么做就是程序错误,它可能会也可能不会被JMS提供商检测到。

参见节4.4.3“创建临时目的地”了解详细信息。

6.7 TopicConnectionFactory

客户端使用TopicConnectionFactory来创建带JMS Pub/Sub提供商的TopicConnection。

参见节4.2“受管理对象”了解JMS ConnectionFactory对象的更多信息。

6.8 TopicConnection

TopicConnection是一个连接到JMS Pub/Sub提供商的活动连接。客户端使用TopicConnection来创建一到多个用于生产和消费消息的TopicSession。

参见节4.3“Connection”了解更多信息。

6.9 TopicSession

TopicSession提供了创建TopicPublisher、TopicSubscriber和TemporaryTopic的方法。它也提供了用于删除客户端永久订阅的unsubscribe方法。

如果已经接收到消息但消息在TopicSession终止时还没有被确认,则永久TopicSubscriber必须保留和重发这些消息;非永久订阅不需要这么做。

参见节4.4“Session”了解更多信息。

6.10 TopicPublisher

客户端使用TopicPublisher向一个topic发布消息。TopicPublisher是JMSMessageProducer的Pub/Sub变量。可以使用MessageProducer想一个Topic 发送消息。参见节4.6“MessageProducer”了解公共特性的描述。

6.11 TopicSubscriber

客户端使用TopicSubscriber来接收已发布到主题的消息。TopicSubscriber是JMSMessageConsumer的Pub/Sub变量。参见节4.5“MessageConsumer”了解更多信息。

普通的TopicSubscriber不是永久性的。它们只接收它们是活动时被发布的消息。

被订阅者的消息选择器过滤掉的消息永远不会被订阅者接收到。从订阅者的角度来看,这些消息是不存在的。

在某些情况下,连接可以既是到主题的发布又是到主题的订阅。订阅者的NoLocal属性可以让订阅者抑制转发由它自己的连接发布的消息。

TopicSession可以为每个目的地创建多个TopicSubscriber,它将目的地的每个消息都转发到符合接收条件的TopicSubscriber。这些都工作在消息的复制品上,而不互相影响;确认一个消息不会确认其他的消息;一个消息可能被立刻转发,但另一个可能等待消费者处理完它前面的消息。

6.11.1 永久TopicSubscriber

如果客户端需要接收发布到主题上的所有消息,包括订阅者是不活动时发布的消息,那么它使用永久TopicSubscriber。永久TopicSubscriber可以由Session 或TopicSession创建。JMS保留永久订阅的记录并保证来自Topic的发布者的所有消息都被保留,直到这些消息被永久订阅者确认或它们到期。

使用永久订阅的会话必须总是提供同一个客户端标识。另外,每个客户端必须指定唯一标识(在客户端标识符中)它创建的每个永久订阅的名字。一次只能有一个会话可以有一个 特殊永久订阅的TopicSubscriber。参见节4.3.2“客户端标识”了解更多信息。

客户端可以通过创建一个具有相同名字和新主题和/或消息选择器或NoLocal属性的永久TopicSubscriber 来改变一个存在的永久订阅。改变一个永久订阅相当于删除并重新创建它。

Session和TopicSession提供了unsubsribe用于删除它们客户端创建的永久订阅。

这回删除由提供商代表订阅者维护的状态。对客户端来说,当永久订阅有活动的TopicSubscriber 或者当被接收到的消息是当前事务的一部分或者还没有在会话中确认时,删除一个永久订阅是错误的。

6.12 恢复和重发

非永久订阅者的未确认消息应当能够在非永久订阅者生存时被恢复。当非永久订阅者终止时,等待它的消息很可能被丢弃而不管是否被确认。

只有永久订阅可以可靠地恢复未确认消息。

向转发模式是PERSISTNET的主题发送消息不会改变恢复和重发的模式。为了保证转发,TopicSubscriber应当设置一个永久订阅。

6.13 管理订阅

理想情况下,发布者和订阅者都是在它们被创建时由提供商动态注册。从客户端视角来看,总是这样的。从管理员的角度看,可能需要其他任务来支持发布者和订阅者的创建。

为消息存储分配的资源的数量和资源过量的结果在JMS中没有定义。

6.14 TopicRequestor

JMS提供了TopicRequestor帮助类来简化服务请求。

TopicRequestor构造器需要传入TopicSession和目的地主题。它为响应创建了一个TemporaryTopic,并提供了发送请求消息的request()方法然后等待回复。

这是最基本的请求/响应抽象,它可以满足大多数的用途。JMS提供者和客户端可以自由地创建多种专业版本。

6.15 可靠性

当主题的所有消息必须被接收时,应当使用永久订阅。JMS保证在永久订阅者不活动时保留发布的消息,并在订阅者活动后将消息转发给它。

非永久订阅者只应当用于可以接受丢失的情况。

表 6.2. Pub/Sub可靠性

如何发布非永久订阅永久订阅
NON_PERSISTENT 

最多一次(如果不活动则丢失)

最多一次
PERSISTENT 

一次只有一个(如果不活动则丢失)

一次只有一个