最近小编在开发项目中,偶然间遇到了这样一个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本地就消费一个。
到这里,问题已然基本解决了,个人感觉,通过消息队列在处理并发异步上是比较方便的。好了,以上如有不足之处,欢迎指正,希望大家多多关注多多支持小编,制作不易!
版权归原作者 吾疾唯君医 所有, 如有侵权,请联系我们删除。