SpringBoot解决RabbitMQ消费几条消息后不再消费的bug

最近小编在开发项目中,偶然间遇到了这样一个bug,在使用本地RabbitMQ时候,生产者生产消息及消费者消费消息都很及时,但是当把项目部署到Linux服务器后,就会发生生产者生产消息后,有时候只有第一条会被消费,有时候消费几条以后,就不再消费了,初见这样的bug,一时百思不得其解,遇到就解决呗,由于项目的业务比较复杂,所以小编做了个RabbitMQ的demo,经过观察,排查,终于发现了bug的原因,在这里作为经验总结给大家。

首先排查配置问题,由于是同样的配置,本地是链接、消息生产和消费是正常的,服务器上也会出现消费,所以对于RabbitMQ的链接是没问题的。

由于出问题的是服务器的RabbitMQ,小编做出的demo 用同样的配置链接服务器的RabbitMQ,IP需要使用服务器的IP,

这里需要注意一点,服务器需要开放5672端口,本地才能链接;RabbitMQ默认的用户名密码是guest,guest,但是由于测试归属于服务器的RabbitMQ,而默认用户是不支持远程链接的,所以小编新建了个远程用户,admin,admin

小编这里简单给大家写一下创建服务器RabbitMQ远程用户并赋予远程权限的指令,百度上有很多。

开启RabbitMQ webui管理

rabbitmq-plugins enable rabbitmq_management

添加用户 rabbitmqctl add_user 用户名 密码

rabbitmqctl add_user admin admin

设置权限

rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"

设置用户角色:rabbitmqctl set_user_tags admin administrator

查看用户列表:rabbitmqctl list_users

RabbitMQ消息生产者:

/**
     * 向直接交换器发送数据
     *
     *
     * @param massage
     */
    public void sendzongheDirectTestQueue(String massage) {
        try{
            rabbitTemplate.convertAndSend(RabbitConfig.zonghe_direct_exchange,
                    RabbitConfig.zonghe_direct_exchange_key, massage);
            System.out.println("发送消息到交换器:"+massage);
        }
        catch (Exception e){
            System.out.println("生产者生产消息出现异常:"+e.getMessage());
        }

    }

RabbitMQ消息消费者:

   /**
     * 监听直接测试队列数据
     * @param massage
     */
    @RabbitListener(
            bindings =
                    {
                            @QueueBinding(value = @Queue(value = RabbitConfig.zonghe_direct_queue, durable = "true"),
                                    exchange = @Exchange(value = RabbitConfig.zonghe_direct_exchange),
                                    key = RabbitConfig.zonghe_direct_exchange_key)
                    })
    @RabbitHandler
    public void zongheprocessDirectMsg(Message massage) {
        String msg = new String(massage.getBody(), StandardCharsets.UTF_8);
        log.info("\r\n接收到综合测试队列 消息==>"+msg);
    }

消息生产调用,小编做了个简单的定时任务,间隔5秒生产一次消息,用随机字符区分消息的不同性。

@Autowired
    private MsgProducer msgProducer;

    @Scheduled(initialDelay = 5000, fixedRate = 5000)
    public void test(){
        try {
            msgProducer.sendzongheDirectTestQueue("我是发送给rabbitmq综合交换器的消息"+StringTimeUtil.nonce(5));
            System.out.println(StringTimeUtil.now()+"间隔5秒发送消息完成");
        }catch (Exception e){
            System.out.println("RabbitMQ发送消息异常:"+e.getMessage());
        }
    }

效果如下:

出现了这样的情况,生产者生产了3条消息后,RabbitMQ demo才消费了最后一条,而消息生产并未出现异常,也就是说,定时任务调用生产者生产消息均是正常的,但demo里面只消费了最后一条消息,之前生产的两条消息不知什么情况,是丢失了还是发生返回了,如果发生返回,后面应该会再次被demo消费掉,但是很久也没有查到之前的两条消息的消费情况。唉,索性小编又开放了服务器的ui管理端口,通过访问服务器RabbitMQ的ui管理来查查吧,同样的,在外面访问ui管理仍然需要使用新建的远程用户进行登录。

由于全是英文,小编也不懂啊,不过因为经常使用,还是能看懂些单词的。小编首先进入交换器。

看样子是没什么异常的,交换器是正常创建的,密钥也正确,durable:true状态也正常。然后查看队列。

看表格这里是正常的,能收到消息,也在消费,点进去查看:

小编发现,关于消息交换器和消息队列绑定也是正常的,也没有发生回传重试,但忽然注意到消息队列的消费者有三个,并且下面的Consumers详细的列出了三个消费者。由此猜想,八成是demo中生产的三条消息,前两条被其他消费者消费掉了,最后一条消息由demo本身的消费者消费了。经过排查测试确实是这样,小编本地开发项目在链接着服务器的RabbitMQ,服务器正运行的项目也在连接着RabbitMQ,加上本地demo正好三个,当把除了demo其他两个服务均关闭后,效果就正常了。

关闭后的web管理界面效果如下:

消费者变成了一个,并且demo的消费也变正常了,生产一个,demo本地就消费一个。

到这里,问题已然基本解决了,个人感觉,通过消息队列在处理并发异步上是比较方便的。好了,以上如有不足之处,欢迎指正,希望大家多多关注多多支持小编,制作不易!

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾疾唯君医

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值