意外的 RabbitMQ 队列特征丢失 (spring-amqp)

问题描述

背景

我们已经使用 spring-amqp 通过 Spring Boot 和 RabbitMQ 实现了重试机制。 RabbitMQ 实例配置为高可用性,具有一个主镜像和两个镜像。配置的唯一策略是影响所有资源(队列和交换)的策略,定义如下。

ha-mode:    all
ha-promote-on-shutdown: always
ha-sync-mode:   automatic

两个 Spring Boot 服务,每个服务都运行 spring-amqp:2.1.6.RELEASE一个服务向主要工作队列发布消息,另一个服务从中消费。

如果消费者不喜欢某条消息,它会尝试将该消息发布到为重试次数相同的消息指定的重试队列。最大重试次数和回退间隔可通过应用程序属性进行配置。重试队列被声明为死信返回主工作队列,由下一个可用的消费者使用。在这种情况下,回退间隔通过 message-ttl 实现,重试消息发布到的队列声明为 message-ttl 值 + 1 分钟的队列到期时间。

首先,遇到有害消息的消费者尝试使用 AmqpAdmin 接口查看队列是否存在。

Properties retryQueueProperties = rabbitAdmin.getQueueProperties(queueName);
if (retryQueueProperties == null) {
    Queue retryQueue = createRetryQueue(currentAttempt);
    declareAndBindRetryQueue(retryQueue);
}

如果所需的重试队列不存在,消费者将声明它。

retryQueue = QueueBuilder.durable(queueName)
    .withArgument("x-dead-letter-exchange",primaryExchangeName)
    .withArgument("x-dead-letter-routing-key",primaryRoutingKey)
    .withArgument("x-message-ttl",ttl)
    .withArgument("x-expires",ttl + 60000)
    .build();

并绑定它。

rabbitAdmin.declareQueue(retryQueue);
rabbitAdmin.declareBinding(
    BindingBuilder
        .bind(retryQueue)
        .to(retryExchange)
        .with(retryQueue.getName())
);

然后立即发送消息。

rabbitTemplate.send(retryExchangeName,queueName,message);

问题

偶尔,我们会通过 RabbitMQ 管理 Web 界面观察,重试队列应该已经过期很久,但仍然没有任何功能。也就是说,重试队列缺少在队列声明中建立的所有关键 x-args,使实现工作(x-expiresx-message-ttl 等...)。

EDIT:这会导致消息丢失,似乎是因为消息过期但不是死信,然而,队列似乎没有特征的事实与此相矛盾;队列的 x-message-ttl 功能也消失了。

我们还没有能够在本地重现这种行为。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...