按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
8。2 并发处理订阅的消息
JMS 提供了一个特殊的工具用于创建MessageConsumer,它可以并发的消费消息。
这个工具将这项工作分成三个角色:
z JMS 提供商——用于转发消息。
z 应用服务器——用于创建消费者和管理由并发MessageListener 对象使用的线程。
z 应用——用目的地和可选的消息选择器定义一个订阅,并提供一个单线程的
MessageListener 类来消费它的消息。应用服务器将构造这个类的多个对象来并发消
费消息。
8。2。1 Session
会话提供了应用服务器使用的三个方法:
z setMessageListener() 和 getMessageListener() ——会话的 MessageListener 通过
ConnectionConsumer 消费分配到这个会话的消息,如后面的几个段落描述。
z run()——会话的MessageListener 依次处理由ConnectionConsumer 分配到会话的消
息。当监听器从最后一个消息处理返回时,run()返回。
应用服务器通常被给一个 MessageListener 类,它包含了由应用程序员编写的处理消息
的单线程代码。应用服务器也被给监听器要消费消息的目的地和消息选择器。
应用服务器将负责创建处理消息处理的JMS Connection,ConnectionConsumer 和Session 。
应用服务器将按需创建MessageListener 实例并将它们注册到它自己的会话中。
由于许多监听器需要使用会话的服务,因此监听器很可能要求将它的会话传入到它的构
造器中。
8。2。2 ServerSession
ServerSession 是一个由应用服务器实现的对象。应用服务器使用它来将一个线程和一个
JMS 会话关联起来。
ServerSession 实现了两个方法:
z getSession()——返回ServerSession 的JMS 会话。
z start()——启动ServerSession 线程的执行,并执行关联的JMS 会话的run 方法。
8。2。3 ServerSessionPool
ServerSessionPool 是一个由应用服务器实现的对象,它提供了用于处理
ConnectionConsumer 的消息的ServerSession 池。
它只有一个方法是getServerSession() 。这个方法从池中删除一个ServerSession 并将它返
回给调用者(假定是ConnectionConsumer ),用于消费一个或多个消息。
JMS 没有说明如何实现池。它可能是一个静态的ServerSession 池,或者它可以使用更专
业的算法来按需动态创建ServerSession 。
如果ServerSessionPool 没有了ServerSession,那么getServerSession()方法可能阻塞。如
51 / 66
…………………………………………………………Page 52……………………………………………………………
果ConnectionConsumer 被阻塞,那么它不能转发新的消息直到ServerSession 返回。
8。2。4 ConnectionConsumer
对于应用服务器来说,连接提供了创建 ConnectionConsumer 的专用工具。它消费的消
息由目的地和消息选择器指定。另外,ConnectionConsumer 必须交给ServerSessionPool 用于
处理它的消息。指定 maxMessages 值用于限制 ConnectionConsumer 一次可以加载到
ServerSession 会话的消息数量。
通常,当拥堵轻微时,ConnectionConsumer 从池中得到一个ServerSession,用一个消息
加载它的会话,然后启动它。当拥堵严重时,消息可能被退回。如果发生退回,
ConnectionConsumer 可以用多个消息来加载每个 Session 。这减少了线程上下文的切换,减
小了某些消息处理排序时资源的使用。
8。2。5 ConnectionConsumer 如何使用ServerSession
由JMS 提供商实现的ConnectionConsumer 使用ServerSession 来处理一到多个到达的消
息。按以下方式做这项工作:
z 从ServerSessionPool 中得到一个ServerSession 。
z 得到ServerSession 的Session 。
z 用一个或多个消息加载Session 。
z 然后其他ServerSession 来消费这些消息。
用于QueueConnection 的ConnectionConsumer 将它的消息加载到QueueSession,同样,
用于TopicConnection 的ConnectionConsumer 加载TopicSession 。
注意,JMS 没有说明 ConnectionConsumer 如何用消息加载 Session 。由于
ConnectionConsumer 和Session 都由同一个JMS 提供商实现,因此它们可以用私有机制完成
这种加载。
8。2。6 应用服务器如何实现ServerSession
JMS 没有说明ServerSession 的实现。下面出现的普通实现解释了这个概念:
z 应用服务器为 ServerSession 创建一个线程,注册 ServerSession 的 runObject 。
runObject 的实现是应用服务器私有的。
z ServerSession 的start 方法调用线程的start 方法。和所有的java 线程一样,调用start
初始化线程的执行并调用线程的runObject。ServerSession。start(ConnectionConsumer)
的调用者和ServerSession 的runObject 现在运行在不同的线程中。
z runObject 将做一些内部处理然后调用会话的 run()方法。在返回时,runObject 将
ServerSession 返回给ServerSessionPool 然后返回。这终止了ServerSession 线程的执
行,并再次循环启动。
8。2。7 结果
JMS 定义了灵活的机制将并发消息消费的工作拆分成适合于每个参与者的角色。
52 / 66
…………………………………………………………Page 53……………………………………………………………
应用程序员提供一种易于书写单线程的MessageListener 实现。
JMS 提供者保持对消息的控制直到它们被转发到MessageListener。这保证它是在消息确
认的直接控制之下。
应用服务器控制ConnectionConsumer 的设置和管理用于执行MessageListener 的线程。
下图解释了三个角色和它们实现的对象间的关系。
下图解释了ConnectionConsumer 将消息转发给MessageListener 的过程。
53 / 66
…………………………………………………………Page 54……………………………………………………………
8。3 XAConnectionFactory
某些应用服务器提供对用于分布式事务的资源分组提供支持。为了在分布式事务中包含
JMS 事务,应用服务器要求JTA 兼容JMS 提供商。JMS 提供商用JMS XAConnectionFactory 暴
露它的JTA 支持,应用服务器使用XAConnectionFactory 来创建XAConnection 。
XAConnectionFactory 提供了和ConnectionFactory 一样的授权选项。
XAConnectionFactory 对象是JMS 受管理对象,就像ConnectionFactory 对象。期望用应
用服务器使