Jms ActiveMQ如何以编程方式重新发送/重试DLQ消息

Jms ActiveMQ如何以编程方式重新发送/重试DLQ消息,jms,activemq,Jms,Activemq,我想创建一个简单的代码片段,从DLQ获取所有消息并将它们重新发送到原始目的地(也称为重新发送/重试) ActiveMQ UI可以轻松地完成此操作(但一次只发送一条消息)。没有直接的JMS API用于将消息从DLQ重新发送到其原始队列。事实上,jmsapi甚至没有讨论死信队列。这只是大多数代理用来处理无法使用的消息的约定 您需要创建一个实际的JMS使用者来接收来自DLQ的消息,然后创建一个JMS生产者来将消息发送回其原始队列 使用Session.transact模式以避免潜在的消息丢失或重复非常重

我想创建一个简单的代码片段,从DLQ获取所有消息并将它们重新发送到原始目的地(也称为重新发送/重试)


ActiveMQ UI可以轻松地完成此操作(但一次只发送一条消息)。

没有直接的JMS API用于将消息从DLQ重新发送到其原始队列。事实上,jmsapi甚至没有讨论死信队列。这只是大多数代理用来处理无法使用的消息的约定

您需要创建一个实际的JMS使用者来接收来自DLQ的消息,然后创建一个JMS生产者来将消息发送回其原始队列

使用
Session.transact
模式以避免潜在的消息丢失或重复非常重要

如果您使用的是
Session.AUTO_ACKNOWLEDGE
,并且消息的使用时间和发送时间之间存在问题(例如,应用程序崩溃、硬件故障等),则消息可能会丢失,因为在成功发送之前已对其进行了确认

如果您使用的是
Session.CLIENT\u ACKNOWLEDGE
,并且在发送和确认消息的时间之间存在问题,则消息最终可能会被复制,因为在成功确认之前,消息已经发送

这两个操作都应该是JMS事务的一部分,以便工作是原子的


最后,我建议您在事务处理会话中为发送的每条消息调用
commit()
,或者在一小批消息(例如10)之后调用。如果您不知道DLQ中有多少条消息,那么在单个事务中处理每条消息是不明智的。通常,您希望事务尽可能小,以最小化可能发生错误的窗口,并且需要再次执行事务的工作。此外,事务越大,代理上需要的堆内存就越多,以跟踪事务中的工作。请记住,您可以在同一会话上调用
commit()
,次数可以根据需要而定。您不需要为每个事务创建新会话。

没有用于将消息从DLQ重新发送到其原始队列的直接JMS API。事实上,jmsapi甚至没有讨论死信队列。这只是大多数代理用来处理无法使用的消息的约定

您需要创建一个实际的JMS使用者来接收来自DLQ的消息,然后创建一个JMS生产者来将消息发送回其原始队列

使用
Session.transact
模式以避免潜在的消息丢失或重复非常重要

如果您使用的是
Session.AUTO_ACKNOWLEDGE
,并且消息的使用时间和发送时间之间存在问题(例如,应用程序崩溃、硬件故障等),则消息可能会丢失,因为在成功发送之前已对其进行了确认

如果您使用的是
Session.CLIENT\u ACKNOWLEDGE
,并且在发送和确认消息的时间之间存在问题,则消息最终可能会被复制,因为在成功确认之前,消息已经发送

这两个操作都应该是JMS事务的一部分,以便工作是原子的


最后,我建议您在事务处理会话中为发送的每条消息调用
commit()
,或者在一小批消息(例如10)之后调用。如果您不知道DLQ中有多少条消息,那么在单个事务中处理每条消息是不明智的。通常,您希望事务尽可能小,以最小化可能发生错误的窗口,并且需要再次执行事务的工作。此外,事务越大,代理上需要的堆内存就越多,以跟踪事务中的工作。请记住,您可以在同一会话上调用
commit()
,次数可以根据需要而定。您不需要为每个事务创建新会话。

在Justin回复后,我手动实现了重试机制,如下所示:

public void retryAllDlqMessages()引发JMSExException{
logger.warn(“retryAllDlqMessages启动”);
warn(“创建到{}的连接”,activemqUrl);
ActiveMQConnectionFactory connectionFactory=新的ActiveMQConnectionFactory(“测试”,“测试”,activemqUrl);
HashMap messageProducersMap=新HashMap();
MessageConsumer=null;
try(ActiveMQConnection连接=(ActiveMQConnection)connectionFactory.createConnection();
ActiveMQSession会话=(ActiveMQSession)connection.createSession(true,session.session_transactived)){
字符串dlqName=getDlqName();
warn(“创建到{}的会话”,dlqName);
ActiveMQQueue队列=(ActiveMQQueue)会话。createQueue(dlqName);
warn(“启动JMS连接”);
connection.start();
logger.warn(“创建DLQ使用者”);
consumer=session.createConsumer(队列);
logger.warn(“消费者开始接收”);
Message Message=consumer.receive(consumer\u receive\u TIME\u,单位:毫秒);
int retriedMessages=0;
while(消息!=null){
试一试{
retryMessage(messageProducersMap、会话、消息);
检索消息++;
}捕获(例外e){
error(“为message={}调用retryMessage时出错”,message);
错误(“回滚JMS事务…”);
session.rollback();
返回;
}
message=consumer.receive(consumer\u receive\u TIME\u,单位:毫秒);
curl -XGET --user admin:admin --header "Origin: http://localhost" http://localhost:8161/api/jolokia/exec/org.apache.activemq:brokerName=localhost,destinationName=ActiveMQ.DLQ,destinationType=Queue,type=Broker/retryMessages