重启rabbitmq后,队列中没有消费者的原因

问题:

      上次生产服务器出问题,导致上面的rabbitmq主节点和一系列应用服务宕机。运维先重启应用服务(消费者)后再启动MQ主节点后发现,主节点队列上堆积的消息没有被消费,点进队列一看,没有消费者!

场景复现:

        在开发环境搭建mq集群,模拟生产场景。

场景重现:

        启动消费者应用,可以发现日志报错信息如下:

解释一下意思就是: 消费者发现没有要监听的 queue 时,默认会进行三次重试监听 queue,三次都失败后就无法重试了(三次时间很短,默认10s一次)

此时就算你重启了MQ,但是消费者不会再去监听mq对应队列了,所以MQ的队列上就不会有消费者信息了。

解决办法:

spring通过发布事件的方式,可以通知观察者(即事件监听器)消费者的一些行为,消费者相关的事件如下所示。

  • AsyncConsumerStartedEvent:An event that is published whenever a new consumer is started.
  • AsyncConsumerStoppedEvent:An event that is published whenever a consumer is stopped (and not restarted).
  • AsyncConsumerRestartedEvent:An event that is published whenever a consumer is restarted.
  • ListenerContainerConsumerFailedEvent:Published when a listener consumer fails.

基于事件机制,可以通过监听事件ListenerContainerConsumerFailedEvent,当有消费者发生致命错误时,重新创建消费者消费消息,并发送告警信息给相关责任人。具体实现如下:

import java.util.Arrays;

import org.springframework.amqp.rabbit.listener.ListenerContainerConsumerFailedEvent;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import lombok.extern.slf4j.Slf4j;

/**
 * MQ消费者失败事件监听器
 * @author wxyh
 * @date 2018/04/02
 */
@Slf4j
@Component
public class ListenerContainerConsumerFailedEventListener implements ApplicationListener<ListenerContainerConsumerFailedEvent> {

    @Override
    public void onApplicationEvent(ListenerContainerConsumerFailedEvent event) {
        log.error("消费者失败事件发生:{}", event);

        if (event.isFatal()) {
            log.error(String.format("Stopping container from aborted consumer. Reason::%s.",
                    event.getReason()), event.getThrowable());
            SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) event.getSource();
            String queueNames = Arrays.toString(container.getQueueNames());
            // 重启
            try {
                restart(container);
                log.info("重启队列%s的监听成功!", queueNames);
            } catch (Exception e) {
                log.error(String.format("重启队列%s的监听失败!", queueNames), e);
            }

            // TODO 告警,包含队列信息,监听断开原因,断开时异常信息,重启是否成功等...

        }
    }

    /**
     * 重启监听
     * @param container
     * @return
     */
    private void restart(SimpleMessageListenerContainer container) {
        // 暂停30s
        try {
            Thread.sleep(30000);
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        Assert.state(!container.isRunning(), String.format("监听容器%s正在运行!", container));
        container.start();
    }

}

参考:一文教你如何解决RabbitMQ队列无消费者

        RabbitMQ异常监控及动态控制队列消费的解决方案

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
RabbitMQ是一种流行的消息队列间件,用于在应用程序之间进行通信和数据交换。当RabbitMQ节点重启后,某些情况下会导致消息无法消费或消费的问题。下面是一些可能的原因和解决方法: 1. 消费者连接断开:当RabbitMQ节点重新启动时,消费者与服务器之间的连接可能会断开。这可能是由于网络错误、配置错误或应用程序问题引起的。解决方法是确保消费者已正确配置,并重新建立连接。 2. 队列丢失:在节点重启后,队列的元数据可能会丢失,导致消息无法被正确识别和消费。这时可以使用RabbitMQ的管理界面或命令行工具,手动创建队列并绑定消费者。 3. 持久化配置问题:如果消息被设置为持久化,但RabbitMQ节点在重启没有正确地加载和恢复这些持久化消息,那么消费者将无法获取到这些消息。确保消息被正确地标记为持久化,并检查RabbitMQ节点的持久化配置。 4. 交换机配置错误:节点重启后,交换机的配置可能会变得不正确,导致消息无法正确路由到队列。检查交换机和队列之间的绑定关系,确保消息可以正确路由到消费者。 5. 死信队列重启后,死信队列可能会被重置,导致消息无法正常地进入死信队列。检查死信队列配置,并确保消息被正确地发送到死信队列。 在解决这些问题之前,我们需要检查RabbitMQ的错误日志以获取更多的细节和指导。重启后无法消费消息的问题通常可以通过逐个检查和修复这些潜在问题来解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值