我们有一个java应用程序运行在WebSphereApplicationServer8.5.5上。有两个进程在单独的JVM中运行。
应用程序正在使用IBM Webhere队列管理器和Oracle 11c数据库进行一些集成。JMS和JDBC资源都配置为使用XA事务。
过程1:
-
阅读来自
消息
排队并提取用于标识相关消息的消息密钥
-
将消息保存到数据库。
-
检查消息密钥是否不存在于
钥匙
表,如果没有,则插入
-
仅当发生上述插入时
它将消息密钥放入
钥匙
队列
-
提交事务
流程2:
-
从
钥匙
队列
-
从中删除消息键
钥匙
桌子
-
处理与从接收到的消息密钥相关联的所有消息
消息
桌子
我们观察到,在从
钥匙
将
流程2
有时无法从中找到要删除的记录
钥匙
表仅在毫秒后可用。多次尝试删除它修复了问题,但很明显,即使
流程1
如果启用了XA,它首先提交JMS资源,然后JDBC在很短的时间内将数据置于不一致的状态。
所以我的问题是:
有没有办法强制事务管理器先提交JDBC,然后提交JMS?
我们发现这个
IBM knowledge center
我们尝试如下配置提交优先级:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-ext_1_0.xsd"
version="1.0">
<session name="RepositoryInstanceFacade">
<resource-ref name="jms/MQConnectionFactory" commit-priority="1" isolation-level="TRANSACTION_READ_COMMITTED"/>
<resource-ref name="jdbc/MessageManagerDB" commit-priority="2" isolation-level="TRANSACTION_READ_COMMITTED"/>
</session>
</ejb-jar-ext>
然而,这并没有解决我们的问题。我相信我们不是唯一面临这个问题的人,但我只是不知道应该做些什么。最后,我们将消息键放回
钥匙
排队解决了问题,但在我看来,这是一个非常非正统的解决方案,而不是一个关键的24 x 7应用程序的好解决方案。
提前感谢您的投入。
更新
我添加了这个资源绑定文件ibm ejb jar bnd。我的ejb应用程序的META-INF文件夹中的xml文件,但仍然不走运。作为部署的一部分,我可以看到IBM操纵了该文件并将其转换为XMI文件
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd"
version="1.0">
<session name="RepositoryInstanceFacade">
<resource-ref name="jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
</session>
</ejb-jar-bnd>
更新2
我在两个JVM中完成了以下配置,每个JVM运行自己的应用程序:
application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"
version="6">
...
<resource-ref>
<description>XA Message Manager Data Source</description>
<res-ref-name>java:app/env/jdbc/MessageManagerDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</application>
ibm-aplication-bnd.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application-bnd
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_0.xsd"
version="1.0">
<resource-ref name="java:app/env/jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
</application-bnd>
ibm-ejb-jar-ext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-ext_1_0.xsd"
version="1.0">
<session name="RepositoryInstanceFacade">
<resource-ref name="java:app/env/jdbc/MessageManagerDB" isolation-level="TRANSACTION_READ_COMMITTED" commit-priority="2"/>
</session>
</ejb-jar-ext>
spring data source bean:
<jee:jndi-lookup id="messageManagerDB" jndi-name="java:app/env/jdbc/MessageManagerDB"/>
然后再次运行我的测试。在测试运行期间,我非常高兴,因为日志中没有出现警告消息。然而,测试运行了几个小时,很难一直手动检查。最后,仍然有三条警告消息显示,在数据库插入可用之前,JMS消息仍然从队列中读取。我还缺什么吗?
注意,根据IBM文档,我去掉了JMS连接工厂的任何设置,它将保持为零,因此它的提交优先级低于JDBC。
更新3
根据评论和IBM支持人员的建议,我最终进行了以下设置:
ejb-jar.xml:
<session name="RepositoryInstanceFacade">
...
<resource-ref>
<description>XA Message Manager Data Source</description>
<res-ref-name>jdbc/MessageManagerDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</session>
ibm-ejb-jar-bnd.xml:
<resource-ref name="jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
ibm-ejb-jar-ext.xml:
<session name="RepositoryInstanceFacade">
<resource-ref name="jdbc/MessageManagerDB" isolation-level="TRANSACTION_READ_COMMITTED" commit-priority="2"/>
</session>
spring data source bean:
<jee:jndi-lookup id="messageManagerDB" jndi-name="java:comp/env/jdbc/MessageManagerDB"/>
有了这些设置,JMS仍然是首先提交的,JDBC是最后提交的,因此它仍然没有按预期工作。