java javax.jms.ConnectionFactory 和 javax.jms.XAConnectionFactory 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4117628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:49:36  来源:igfitidea点击:

Differences between javax.jms.ConnectionFactory and javax.jms.XAConnectionFactory

javajmsjndijtaatomikos

提问by Ittai

I'm entering the world of JTA, due to need of distributed transactions, and I'm uncertain about the differences between javax.jms.ConnectionFactoryand javax.jms.XAConnectionFactoryor more accurately how can it be that javax.jms.ConnectionFactoryperformed what I expected only javax.jms.XAConnectionFactorycan do for me.

由于需要分布式事务,我正在进入 JTA 的世界,我不确定两者之间的差异javax.jms.ConnectionFactoryjavax.jms.XAConnectionFactory或者更准确地说,它如何javax.jms.ConnectionFactory执行我期望的只能javax.jms.XAConnectionFactory为我做的事情。

The details: I'm using Atomikos essentials as my transaction manager and my app is running on Apache Tomcat 6.

详细信息:我使用 Atomikos Essentials 作为我的事务管理器,我的应用程序在 Apache Tomcat 6 上运行。

I'm running a small POC with a dummy app where I have my JMS provider (OpenMQ) registered as a JNDIresource.

我正在运行一个带有虚拟应用程序的小型 POC,我将 JMS 提供程序 ( OpenMQ) 注册为JNDI资源。

<Resource name="jms/myConnectionFactory" auth="Container"  
 type="com.atomikos.jms.AtomikosConnectionFactoryBean"  
 factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"   
uniqueResourceName="jms/myConnectionFactory"  
xaConnectionFactoryClassName="com.sun.messaging.XAConnectionFactory"  
maxPoolSize="3"/>

And the strange issue is that in my code I do this:

奇怪的问题是,在我的代码中,我这样做了:

Context ctx = new InitialContext();  
ConnectionFactory queueConnectionFactory =  
(ConnectionFactory)ctx.lookup("java:comp/env/jms/myQueueFactory");  
javax.jms.Connection connection = queueConnectionFactory.createConnection();  
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

And later in the code I use this session in a UserTransactionand it performs flawlessly with two MessageProducers with either Commitor Rollback.

后来在代码中,我在 a 中使用了这个会话UserTransaction,它在两个MessageProducers 中完美地执行,Commit或者Rollback

What I don't understand is how can it be that I'm using javax.jms.XAConnectionFactory.createConnection()method and I get a Sessionwhich does the job? What's javax.jms.XAConnectionFactoryrole?

我不明白的是,我怎么会使用javax.jms.XAConnectionFactory.createConnection()方法并且我得到一个Session可以完成这项工作的方法?有什么javax.jms.XAConnectionFactory作用?

I'll also add that I've looked at the source code of both classes (and javax.jms.BasicConnectionFactory) and I verified that the XA class does not override createConnection.

我还要补充一点,我已经查看了两个类(和javax.jms.BasicConnectionFactory)的源代码,并验证了 XA 类没有覆盖createConnection.

采纳答案by Nicholas

The core of the difference between ConnectionFactory and XAConnectionFactory is that the XAConnectionFactory creates XAConnections which create XASessions. XASessions represent the real difference because (to quote from the JMS JavaDocs:)

ConnectionFactory 和 XAConnectionFactory 的核心区别在于 XAConnectionFactory 创建了 XAConnections,而 XAConnections 又创建了 XASessions。XASessions 代表了真正的区别,因为(引用自JMS JavaDocs:)

The XASession interface extends the capability of Session by adding access to a JMS provider's support for the Java Transaction API (JTA) (optional). This support takes the form of a javax.transaction.xa.XAResource object.

XASession 接口通过添加对 JMS 提供者对 Java 事务 API (JTA)(可选)支持的访问来扩展 Session 的功能。这种支持采用 javax.transaction.xa.XAResource 对象的形式。

In other words, the XASession is what gives the XA instances their transactional awareness. However, this specific implementation is optional, even for a fully compliant JMS provider. From the same JavaDoc:

换句话说,XASession 使 XA 实例具有事务意识。然而,这个特定的实现是可选的,即使对于完全兼容的 JMS 提供者也是如此。来自同一个 JavaDoc:

An XAResource provides some fairly sophisticated facilities for interleaving work on multiple transactions, recovering a list of transactions in progress, and so on. A JTA aware JMS provider must fully implement this functionality. This could be done by using the services of a database that supports XA, or a JMS provider may choose to implement this functionality from scratch. A client of the application server is given what it thinks is a regular JMS Session. Behind the scenes, the application server controls the transaction management of the underlying XASession.

XAResource 提供了一些相当复杂的工具,用于在多个事务上交错工作、恢复正在进行的事务列表等。JTA 感知 JMS 提供程序必须完全实现此功能。这可以通过使用支持 XA 的数据库服务来完成,或者 JMS 提供者可以选择从头开始实现此功能。应用程序服务器的客户端被赋予它认为是常规 JMS 会话的内容。在幕后,应用服务器控制底层 XASession 的事务管理。

In other words, the provider may require that you specify an XA or non-XA JMS resource, or, as would seem to be in your case, the provider may perform all the JTA plumbing transparently with what appears to be a regular JMS Session.

换句话说,提供者可能要求您指定 XA 或非 XA JMS 资源,或者,就像您的情况一样,提供者可能会使用看似常规的 JMS Session透明地执行所有 JTA 管道。

回答by T.Rob

Actually, none of the example code you provided would exercise XA functionality. If all that is required is that your messages are under syncpoint, then you can get by with 1-phase commit (1PC). However if you want, for example, that JMS messages and DB updates occur in a single coordinated unit of work then you would use 2-phase commit (2PC) which is XA. Coordinating across two message producers on the same transport provider does not require XA 2PC.

实际上,您提供的示例代码都不会使用 XA 功能。如果所需要的只是您的消息在同步点下,那么您可以使用 1 阶段提交 (1PC)。但是,例如,如果您希望 JMS 消息和数据库更新发生在单个协调工作单元中,那么您将使用两阶段提交 (2PC),即 XA。在同一个传输提供者上的两个消息生产者之间进行协调不需要 XA 2PC。

If you were using 2PC, then in addition to COMMIT and ROLLBACK you would be calling BEGIN somewhere in the code. The lack of that verb in your example is why I said it looks like you are not doing 2PC. The BEGIN call would communicate with the transaction manager to establish a transaction context across the participating resource managers. Then the COMMIT would cause the messages andthe DB updates to finalize in one unit of work. The interesting thing here is that if you have only one participating resource manager, some transports will silently optimize you back down to 1PC. In that case it looks as though you are doing 2PC but are really getting 1PC. Since there is only one resource manager there is no loss of reliability in this optimization.

如果您使用的是 2PC,那么除了 COMMIT 和 ROLLBACK 之外,您还会在代码中的某处调用 BEGIN。在您的示例中缺少该动词就是为什么我说您似乎没有在做 2PC。BEGIN 调用将与事务管理器通信以在参与的资源管理器之间建立事务上下文。然后 COMMIT 将导致消息数据库更新在一个工作单元中完成。有趣的是,如果您只有一个参与的资源管理器,某些传输会悄悄地将您优化回 1PC。在那种情况下,看起来好像你在做 2PC,但实际上是在做 1PC。由于只有一个资源管理器,因此在此优化中不会损失可靠性。

On the other hand, if you are doing 1PC you won't see any difference between the two types of connection factory. It would exhibit exactly the behavior you describe.

另一方面,如果您使用 1PC,您将看不到两种连接工厂之间的任何区别。它将完全表现出您所描述的行为。

The last case to consider is that you use ConnectionFactory and try to call BEGIN. Since the non-XA connection factory cannot participate in a coordinated XA transaction, this call should fail.

要考虑的最后一种情况是您使用 ConnectionFactory 并尝试调用 BEGIN。由于非 XA 连接工厂无法参与协调的 XA 事务,因此该调用应该失败。