Java ActiveMQ—保留已使用的消息,直到它';s确认删除

Java ActiveMQ—保留已使用的消息,直到它';s确认删除,java,spring-boot,activemq,Java,Spring Boot,Activemq,我有一个Spring启动应用程序正在侦听ActiveMQ队列 有没有一种方法可以告诉ActiveMQ保留已使用的消息,直到收到从我的服务中删除消息的确认 我的场景是,我从队列中读取消息,一旦消息被消耗,我就将其发送到外部队列。如果外部服务无法处理该消息,我将丢失该消息。我可以告诉active mq保留已消费的消息,直到收到要删除的确认。最安全的选择是使用XA事务以原子方式执行消费/发送(假设发送消息的代理支持XA)。我不确定在Spring中这有多容易或难,但我知道在JavaEE容器中这很简单。您

我有一个Spring启动应用程序正在侦听ActiveMQ队列

有没有一种方法可以告诉ActiveMQ保留已使用的消息,直到收到从我的服务中删除消息的确认


我的场景是,我从队列中读取消息,一旦消息被消耗,我就将其发送到外部队列。如果外部服务无法处理该消息,我将丢失该消息。我可以告诉active mq保留已消费的消息,直到收到要删除的确认。

最安全的选择是使用XA事务以原子方式执行消费/发送(假设发送消息的代理支持XA)。我不确定在Spring中这有多容易或难,但我知道在JavaEE容器中这很简单。

您可以使用确认单个消息的个人确认模式。以下是相同的代码:

    import javax.jms.Connection;
    import javax.jms.JMSException;

    import org.apache.activemq.ActiveMQConnectionFactory;
    import org.apache.activemq.ActiveMQMessageConsumer;
    import org.apache.activemq.ActiveMQSession;
    import org.apache.activemq.command.ActiveMQTextMessage;

    public class SimpleConsumer {

        public static void main(String[] args) throws JMSException {
            Connection conn = null;
            try {
                ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
                conn = cf.createConnection("consumer", "consumer");
                ActiveMQSession session = (ActiveMQSession) conn.createSession(false,
                        ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
                ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer) session
                        .createConsumer(session.createQueue("QUEUE"));
                conn.start();
                ActiveMQTextMessage msg = null;
                while ((msg = (ActiveMQTextMessage) consumer.receive()) != null) {
                    System.out.println("Received message is: " + msg.getText());
               // Call your service and ack the message if successfully processed                    
                 msg.acknowledge();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

作者最初的问题是,当已消费的消息被确认但发送的消息失败时,消息“丢失”。此解决方案打开了另一个问题的大门,即消息可以成功发送,但无法确认(例如,由于网络中断),从而导致重新发送和重复发送消息。如果发送消息是幂等的,则这不是问题,但如果是幂等的,则使用者需要能够检测重复项,或者整个过程需要是原子的(例如,使用XA)。