Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring boot ActiveMQ重新交付不起作用_Spring Boot_Activemq_Dead Letter - Fatal编程技术网

Spring boot ActiveMQ重新交付不起作用

Spring boot ActiveMQ重新交付不起作用,spring-boot,activemq,dead-letter,Spring Boot,Activemq,Dead Letter,我正在尝试使用ActiveMQ实现死信队列。不幸的是,这方面的文档在某些方面相当模糊,我似乎无法正确设置所有内容 我配置了以下bean: @Bean public JmsTemplate createJMSTemplate() { logger.info("createJMSTemplate"); JmsTemplate jmsTemplate = new JmsTemplate(getActiveMQConnectionFactory()); jmsTemplate.s

我正在尝试使用ActiveMQ实现死信队列。不幸的是,这方面的文档在某些方面相当模糊,我似乎无法正确设置所有内容

我配置了以下bean:

@Bean
public JmsTemplate createJMSTemplate() {
    logger.info("createJMSTemplate");
    JmsTemplate jmsTemplate = new JmsTemplate(getActiveMQConnectionFactory());
    jmsTemplate.setDefaultDestinationName(queue);
    jmsTemplate.setDeliveryPersistent(true);
    jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
    return jmsTemplate;
}

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(getActiveMQConnectionFactory());
    factory.setConcurrency("1-10");
    factory.setSessionTransacted(false);
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}

@Bean
public ConnectionFactory getActiveMQConnectionFactory() {
    // Configure the ActiveMQConnectionFactory
    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
    activeMQConnectionFactory.setBrokerURL("tcp://127.0.0.1:61616");
    activeMQConnectionFactory.setTrustedPackages(Arrays.asList("com.company"));

    // Configure the redeliver policy and the dead letter queue
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
    redeliveryPolicy.setInitialRedeliveryDelay(0);
    redeliveryPolicy.setRedeliveryDelay(10000);
    redeliveryPolicy.setUseExponentialBackOff(true);
    redeliveryPolicy.setMaximumRedeliveries(3);
    RedeliveryPolicyMap redeliveryPolicyMap = activeMQConnectionFactory.getRedeliveryPolicyMap();
    redeliveryPolicyMap.put(new ActiveMQQueue(queue), redeliveryPolicy);
    activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);

    return activeMQConnectionFactory;
}
这是我的接收代码:

@Autowired
private ConnectionFactory connectionFactory;

private static Logger logger = LoggerFactory.getLogger(QueueReceiver.class);
private Connection connection;
private Session session;
private SegmentReceiver callback;

@PostConstruct
private void init() throws JMSException, InterruptedException {
    logger.info("Initializing QueueReceiver...");
    this.connection = connectionFactory.createConnection();
    this.session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    Queue q = session.createQueue(queue);
    logger.info("Creating consumer for queue '{}'", q.getQueueName());
    MessageConsumer consumer = session.createConsumer(q);
    this.callback = new SegmentReceiver();
    consumer.setMessageListener(callback);
    this.connection.start();
}

@PreDestroy
private void destroy() throws JMSException {
    logger.info("Destroying QueueReceiver...");
    this.session.close();
    this.connection.close();
}

private class SegmentReceiver implements MessageListener {

    @Override
    public void onMessage(Message message) {
        logger.info("onMessage");
        try {
            TextMessage textMessage = (TextMessage) message;
            Segment segment = Segment.fromJSON(textMessage.getText());
            if (segment.shouldFail()) {
                throw new IOException("This segment is expected to fail");
            }
            System.out.println(segment.getText());
            message.acknowledge();
        }
        catch(IOException | JMSException exception) {
            logger.error(exception.toString());
            try {
                QueueReceiver.this.session.rollback();
            } catch (JMSException e) {
                logger.error(e.toString());
            }
            throw new RuntimeException(exception);
        }
    }

}
然而,什么也没有发生。我使用的是使用默认配置的现成Apache ActiveMQ 5.14.2设置。我错过了什么

因为您正在使用
this.session=connection.createSession(false,session.CLIENT\u确认)
调用
message.acknowledge()
与调用
session.acknowledge()相同

要使ActiveMQ重新交付成功地与您的配置一起工作,有一些可能只需进行最小的更改:

  • 调用
    QueueReceiver.this.session.recover()
    代替调用
    QueueReceiver.this.session.rollback()
  • void org.apache.activemq.ActiveMQSession.recover()引发JMSException

    停止此会话中的邮件传递,并重新启动邮件传递 使用最早的未确认消息

    所有消费者都以串行顺序传递消息。承认 接收到的消息会自动确认已发送的所有消息 已交付给客户

    重新启动会话会导致会话执行以下操作:•停止 邮件传递•标记所有可能已传递的邮件 但未确认为“重新交付”•重新启动交付顺序 包括以前收到的所有未确认的邮件 交付。重新传递的消息不必以精确的方式传递 他们的原始交货单

  • 使用
    this.session=connection.createSession(false,org.apache.activemq.ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE)
    打电话
    
    ((org.apache.activemq.command.ActiveMQMessage)消息)
    ,请注意,不调用此方法就像回滚一样,意味着消息未被确认,并且在
    onMessage
    方法中引发异常将调用
    QueueReceiver.this.consumer.rollback()

  • 只需调用
    QueueReceiver.this.consumer.rollback()org.apache.activemq.ActiveMQMessageConsumer.rollback()代替调用
    QueueReceiver.this.session.rollback()


  • 因此,事实证明这是一系列问题的结合:

    • 会话确认模式需要设置为
      ActiveMQSession.INDIVIDUAL_acknowledge
    • 我使用的是
      session.recover()
      而不是
      rollback()
    • ActiveMQ代理未正确配置。我需要将此位添加到activemq.xml配置文件中(将其放在
      标记下)

      
      
    • 确保您没有激活任何可能会干扰ActiveMQConnectionFactory配置的
      redeliveryPlugin


    我似乎在使用
    ActiveMQSession.INDIVIDUAL\u ACKNOWLEDGE
    this.session.rollback()创建会话方面取得了一些成功。消息仅在应用程序停止时添加到DLQ,但它似乎会无限次重试消息,而不是我配置的3次重新传递。
    
        <destinationPolicy>
        <policyMap>
          <policyEntries>
            <policyEntry topic=">" >
                <!-- The constantPendingMessageLimitStrategy is used to prevent
                     slow topic consumers to block producers and affect other consumers
                     by limiting the number of messages that are retained
                     For more information, see:
    
                     http://activemq.apache.org/slow-consumer-handling.html
    
                -->
              <pendingMessageLimitStrategy> 
                <constantPendingMessageLimitStrategy limit="1000"/>
              </pendingMessageLimitStrategy>
            </policyEntry>
            <!-- Set the following policy on all queues using the '>' wildcard -->
            <policyEntry queue=">">
                <deadLetterStrategy>
                    <!--
                      Use the prefix 'DLQ.' for the destination name, and make
                      the DLQ a queue rather than a topic
                    -->
                    <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>
                </deadLetterStrategy>
            </policyEntry>
          </policyEntries>
        </policyMap>
    </destinationPolicy>