问题描述
背景
我们已经使用 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-expires
、x-message-ttl
等...)。
EDIT:这会导致消息丢失,似乎是因为消息过期但不是死信,然而,队列似乎没有特征的事实与此相矛盾;队列的 x-message-ttl
功能也消失了。
我们还没有能够在本地重现这种行为。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)