简体   繁体   English

为什么 MDB 消费者再次从 ActiveMQ 中获取消息?

[英]Why is the MDB consumer picking up the message from ActiveMQ again?

I have an MDB consumer with settings我有一个带有设置的 MDB 使用者

@MessageDriven(name = "PackageReceiver", activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationLookup",
                                  propertyValue = "myQueue"),
        @ActivationConfigProperty(propertyName = "destinationType",
                                  propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode",
                                  propertyValue = "Auto-acknowledge")
})

The message processing process can last from a few seconds to several hours.消息处理过程可能会持续几秒钟到几个小时。

I understand that some kind of timeout is triggered during which there is no acknowledge for the broker (there is no transaction commit)我知道触发了某种超时,在此期间没有对代理的确认(没有事务提交)

Also I understand that there are only two acknowledge modes for MDB: Auto-acknowledge and Dups-ok-acknowledge .另外我知道 MDB 只有两种确认模式: Auto-acknowledgeDups-ok-acknowledge For both options, the message is in the queue until the end of processing the onMessage() method, and using message.acknowledge() does not have the expected effect.对于这两个选项,消息都在队列中,直到处理onMessage()方法结束,并且使用message.acknowledge()没有预期的效果。 Please, help me solve this problem!请帮我解决这个问题!

The onMessage() method of an MDB executes in the context of a JTA transaction by default.默认情况下,MDB 的onMessage()方法在 JTA 事务的上下文中执行。 In this situation the acknowledgeMode is ignored.在这种情况下, acknowledgeMode模式被忽略。 The message is only acknowledged when the JTA transaction is committed (which is done implicitly when onMessage() returns or can be done explicitly using javax.ejb.EJBContext.getUserTransaction() ).仅在提交 JTA 事务时才确认消息(在onMessage()返回时隐式完成,或者可以使用javax.ejb.EJBContext.getUserTransaction()显式完成)。

What's likely happening is that when your MDB takes a long time the JTA transaction is timing out and rolling back which causes the message to go back to the queue and get redelivered.可能发生的情况是,当您的 MDB 花费很长时间时,JTA 事务超时并回滚,这导致发送到 go 的消息返回队列并重新传递。

To resolve this you could extend the transaction timeout (which depends on your application server) or disable JTA transations on your onMessage() (eg using @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.NOT_SUPPORTED ). Long-running transactions are generally considered an anti-pattern therefore I would recommend against extending the timeout. However, if you're working with any other transactional resources (eg JDBC, JMS, etc.) in your onMessage() then disabling JTA transactions could compromise the integrity of your data. Ultimately how you proceed will depend on your specific use-case.要解决此问题,您可以延长事务超时(取决于您的应用程序服务器)或禁用onMessage()上的 JTA 事务(例如使用@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.NOT_SUPPORTED )。长时间运行的事务是通常被认为是反模式,因此我建议不要延长超时时间。但是,如果您在onMessage()中使用任何其他事务资源(例如 JDBC、JMS 等),那么禁用 JTA 事务可能会损害你的数据最终你如何进行将取决于你的具体用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM