Artemis ActiveMQ + MDB 长时间工作:重新交付前等待多长时间
Artemis ActiveMQ + MDB long time work: how long it wait before redelivery
我有 Wildfly 21.0.0 配置了 jms-queue 和几个 in-vm connector/acceptor。
然后我有一个消息驱动 Bean (MDB),最多有 5 个并发会话,而不是处理收到的消息并做一些脏活。
在某些情况下,工作时间超过 5 分钟,而且队列会重新将消息传递给 MDB,从而造成混乱。
我了解重新传递概念、重新传递延迟...,但我没有找到任何关于 Artemis ActiveMQ 在声明消息处于传递状态(等待自动确认)之前等待多长时间的文档onMessage 方法长时间执行结束)必须重新传递。
从日志我认为它等待 5 分钟,然后在重新传递延迟 2 秒后重新传递消息。
这个时间可以配置吗?
谢谢!
<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">
<server name="default">
<in-vm-connector name="in-vm" server-id="0"/>
<in-vm-acceptor name="in-vm" server-id="0">
<param name="buffer-pooling" value="false"/>
</in-vm-acceptor>
<jms-queue name="MyJobsQueue" entries="java:/jms/MyJobsQueue" />
<pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="none" pre-acknowledge="true"/>
</server>
</subsystem>
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MyJobsQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "5")
})
public class MyJobsListener implements MessageListener {
//new logger.....
@Override
public void onMessage(Message m) {
try {
logger.info("Received message ({}) (Redelivered:{})", m.getJMSMessageID(), m.getJMSRedelivered());
Thread.sleep(10 * 60 * 1000);
} catch (InterruptedException e) {
}
}
}
2020-11-19 04:00:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:false)
2020-11-19 04:05:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:10:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:15:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:45:24 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
MDB(就像所有其他类型的 EJB 一样)隐式支持 JTA 事务,一旦 MDB 收到消息,容器就会启动事务。这样做是为了在处理消息时完成的任何事务性工作(例如更新数据库、发送另一条 JMS 消息等)都将成为使用消息本身的事务的一部分。通过这种方式,一条消息可以是一个“工作单元”。
因此请务必注意,WildFly 中的默认事务超时为 300 秒(即 5 分钟)。一旦事务超时,消息将回滚到队列中并可能重新传递。当然,重新交付的工作方式最终取决于代理的配置。
在任何情况下,您都可以通过使用以下注释禁用 JTA 事务来防止长 运行 MDB 出现此类问题:
@TransactionAttribute(NOT_SUPPORTED)
如果您不想为 MDB 禁用容器管理的事务,您可以通过将 default-timeout
属性添加到 <subsystem xmlns="urn:jboss:domain:transactions:5.0">
中的 coordinator-environment
元素来更改默认事务超时,例如:
<coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}" default-timeout="600"/>
但是,请记住,长 运行 事务是一种反模式,因此我不鼓励您增加超时。
我有 Wildfly 21.0.0 配置了 jms-queue 和几个 in-vm connector/acceptor。 然后我有一个消息驱动 Bean (MDB),最多有 5 个并发会话,而不是处理收到的消息并做一些脏活。 在某些情况下,工作时间超过 5 分钟,而且队列会重新将消息传递给 MDB,从而造成混乱。
我了解重新传递概念、重新传递延迟...,但我没有找到任何关于 Artemis ActiveMQ 在声明消息处于传递状态(等待自动确认)之前等待多长时间的文档onMessage 方法长时间执行结束)必须重新传递。 从日志我认为它等待 5 分钟,然后在重新传递延迟 2 秒后重新传递消息。
这个时间可以配置吗?
谢谢!
<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">
<server name="default">
<in-vm-connector name="in-vm" server-id="0"/>
<in-vm-acceptor name="in-vm" server-id="0">
<param name="buffer-pooling" value="false"/>
</in-vm-acceptor>
<jms-queue name="MyJobsQueue" entries="java:/jms/MyJobsQueue" />
<pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="none" pre-acknowledge="true"/>
</server>
</subsystem>
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "MyJobsQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "5")
})
public class MyJobsListener implements MessageListener {
//new logger.....
@Override
public void onMessage(Message m) {
try {
logger.info("Received message ({}) (Redelivered:{})", m.getJMSMessageID(), m.getJMSRedelivered());
Thread.sleep(10 * 60 * 1000);
} catch (InterruptedException e) {
}
}
}
2020-11-19 04:00:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:false)
2020-11-19 04:05:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:10:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:15:00 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
2020-11-19 04:45:24 INFO - Received message (ID:5002ad76-2a13-11eb-bedf-005056b94ad2) (Redelivered:true)
MDB(就像所有其他类型的 EJB 一样)隐式支持 JTA 事务,一旦 MDB 收到消息,容器就会启动事务。这样做是为了在处理消息时完成的任何事务性工作(例如更新数据库、发送另一条 JMS 消息等)都将成为使用消息本身的事务的一部分。通过这种方式,一条消息可以是一个“工作单元”。
因此请务必注意,WildFly 中的默认事务超时为 300 秒(即 5 分钟)。一旦事务超时,消息将回滚到队列中并可能重新传递。当然,重新交付的工作方式最终取决于代理的配置。
在任何情况下,您都可以通过使用以下注释禁用 JTA 事务来防止长 运行 MDB 出现此类问题:
@TransactionAttribute(NOT_SUPPORTED)
如果您不想为 MDB 禁用容器管理的事务,您可以通过将 default-timeout
属性添加到 <subsystem xmlns="urn:jboss:domain:transactions:5.0">
中的 coordinator-environment
元素来更改默认事务超时,例如:
<coordinator-environment statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}" default-timeout="600"/>
但是,请记住,长 运行 事务是一种反模式,因此我不鼓励您增加超时。