我可以在 MDB 中获取源 JMS 会话吗?

Posted

技术标签:

【中文标题】我可以在 MDB 中获取源 JMS 会话吗?【英文标题】:Can I get the source JMS Session in an MDB? 【发布时间】:2012-08-25 21:09:06 【问题描述】:

这个问题主要集中在使用 Websphere MQ (WMQ) 时的 Websphere Application Server (WAS),因为这是我最熟悉的。但是,我认为我所说的一切更普遍地适用于所有 Java EE 应用程序服务器,因为我坚持使用 Java 标准接口。我更喜欢与标准相关的解释,但我仍然会对特定于 WAS/WMQ 的答案感到非常兴奋。

JMS 1.1 为 JMS 定义了一种与应用服务器交互的机制。粗略的过程是在某个时候创建​​ ConnectionConsumer 来监视队列或主题。当消息出现时,JMS 实现从 ServerSessionPool 中获取一个 ServerSession 对象,将消息加载到与 ServerSession 关联的 Session 中,然后在 ServerSession 对象上调用 start()。然后,ServerSession 负责调度消息以供 MDB 在应用程序服务器线程上处理。 MDB 将消息作为其 onMessage() 方法的一部分获取,并且可以进行任何需要的处理。

这一切都很好,直到 MDB 决定它想要发送另一条消息来响应它收到的消息。为此,MDB 必须查找或注入 ConnectionFactory 对象,获取 Connection,然后是 Session,然后是 MessageProducer,最后发送消息。这一切似乎都很浪费。作为向 MDB 传递消息的一部分,已经创建了 Connection 和 Session 对象。如果 MDB 能够以某种方式访问​​该会话,它就可以避免必须做所有这些额外的工作并避免必须创建所有这些额外的连接。作为成本的额外工作 - 为了只向请求消息发送回复消息,MDB 必须使用两个连接和两个会话(每个会话用于获取消息并发送响应)。当使用全局事务时,我相信这会迫使应用程序服务器将事务处理为两阶段提交事务(至少一些,如果不是全部,应用程序服务器可以优化只涉及单个资源的全局事务,将其处理为一阶段提交)。使事务成为两阶段事务显着增加了处理消息的开销,并且还引入了各种新的复杂性(不确定事务是最大的事务之一)。

JMS 1.1 规范指出:“由于许多侦听器将需要使用其会话的服务,因此侦听器可能要求将其会话作为构造函数参数传递给它”,这似乎表明它是完美的MDB 可接受使用传递初始消息的会话也发送响应。但是,我不知道以标准方式从 MDB 检索此 Session 对象的任何机制。我也不知道以非标准方式检索它的任何机制。我什至在任何地方都找不到关于此的问题或博客文章。

所以,问题是:为什么会这样? JMS API 相当复杂,但是,我看不出其中有任何东西会使 MDB 难以使用为它提供原始消息的 Session 来发送响应(如果它可以访问它)。 MDB 不能使用这个 Session 对象有什么原因吗?是否有符合标准的方法来访问会话?有不符合标准的方法吗?应用程序服务器/JMS 实现是否可以智能地将涉及单个 JMS 队列管理器上的两个连接上的操作的全局事务优化为单阶段提交事务(我对标准的研究和理解似乎表明这是不可能的)?

【问题讨论】:

哇!!!你怎么能写这么多??? 天哪,我听到了。我必须马上回复,但我在手机上,我需要输入很多东西。明天回答。 【参考方案1】:

应用服务器/JMS 实现是否智能以优化 涉及单个连接上的两个连接上的操作的全局事务 JMS 队列管理器变成一个单阶段提交事务(我的研究和 对标准的理解似乎表明这是不可能的)?

我的理解是:JMS是一种特殊的JCA连接器。通常,连接器内部有一个与物理连接匹配的托管连接池。一个托管连接一次只能参与一个事务(但事务可以暂停和恢复,所以有点复杂)。 bean 获得的是连接句柄。如果 bean 从给定事务中获取多个连接句柄,则句柄由相同的托管连接支持,这意味着它不应该涉及分布式事务。

当然,这取决于连接器和应用服务器的实现。实际上,您可以通过将 JMS 资源配置为非 XA (there should be an option where you can enable/disable XA support) 来尝试此操作,并查看是否可以在 MDB 中接收消息并将另一条消息发送到队列。它有效,这意味着不涉及分布式事务。

注意:一个常见的优化是“Last Resource Optimization”,它允许分布式事务中的一个参与者实际上是本地参与者,将其用作最后一个资源。最后一个参与者永远不会知道它属于分布式事务。

【讨论】:

以上是关于我可以在 MDB 中获取源 JMS 会话吗?的主要内容,如果未能解决你的问题,请参考以下文章

MDB 和 JMS 的区别

是否可以在运行时手动将消息驱动 bean 订阅到 JMS 队列/主题?

JavaEE- 带有 JMS 和 MDB 的消息传递系统

Wildfly JMS:当消息存在时,MDB bean 空闲

破坏者还是 JMS?

JMS 和 Weblogic 集群