计算机系统应用教程网站

网站首页 > 技术文章 正文

软件性能测试常见的RabbitMQ消息问题分析与处理

btikc 2024-09-01 15:52:01 技术文章 18 ℃ 0 评论

大家好,今天一起聊聊在软件性能测试过程中,可能会出现的RabbitMQ消息队列阻塞等问题影响到性能。


RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。最大的特点是消费并不需要确保提供方实现,实现了服务之间的高度解耦


在了解RabbitMQ,我们先看一张图,图中展示的是RabbitMQ的工作模型,根据这张图,下面理解起来就比较容易了


常见的问题有以下几种情况:RabbitMQ线上消息积压、重复消费、消息丢失解决方案


一、消息堆积
1. 消息堆积的后果
新消息无法进入队列、旧消息无法丢失、消息等待消费时间过长以至于超出了业务容许的范围。


2. 消息堆积的原因
生产者突然大量发布消息、消费者来不及消费或消费失败、消费者出现性能瓶颈、消费者直接挂掉了。消费者宕机积压、消费者消费能力不足积压、发送者发送流量太大


3. 如何解决消息堆积
(1)排查生产者,是否突然大量发布消息,限制下
(2)排查消费者,消费性能瓶颈,增加消费者的多线程处理(缩短线程休眠时间等)、部署多个消费者
(3)排查消息队列,可以想办法把消息按顺序的转移到另外一个新的队列,让消费者消费新队列中的消息。
(4)可以通过修改RabbitMQ的两个参数来增大消费消息的并发数:

concurrentConsumers:对每个listener在初始化的时候设置的并发消费者的个数。

prefetchCount:每次一次性从broker里面取的待消费的消息的个数,
prefetchCount是BlockingQueueConsumer内部维护的一个阻塞队LinkedBlockingQueue 的大小,其作用就是如果某个消费者队列阻塞,就无法接收新的消息,该消息会发送到其它未阻塞的消费者。


二、消息丢失(消息分别在生产者、消息队列、消费者中丢失)
1. 消息在生产者丢失
原因:生产者发送消息成功,但MQ没收到该消息,一般由网络不稳定造成。


解决方案:发送方采用消息确认机制,当消息成功被MQ接收到后,会给生产者发送一个确认消息,表示接收成功。RabbitMQ发送方确认模式有三种,普通确认、批量确认、异步确认。Spring整合RabbitMQ后只使用了异步监听确认模式。

2. 消息在队列中丢失
原因:消息发送到MQ后,消息还没被消费却在MQ中丢失了。比如MQ服务器宕机或者未进行持久化就进行了重启。

解决方案:持久化交换机(Exchange)、队列、消息。确保MQ服务器异常重启时仍然能从磁盘恢复对应的交换机,队列和消息。然后我们把MQ做多台分布式集群,防止出现某一MQ服务器挂掉~

3. 消息在消费者丢失
原因:默认消费者消费消息时,设置的是自动回复MQ收到了消息。MQ会立刻删除自身保存的这条消息,如果消息已经在MQ中被删除,但消费者的业务处理出现异常或消费者服务宕机,那么就会导致该消息没有处理成功从而导致消息丢失。


解决方案:消费者向MQ的回复我们设置成手动回复(配置成手动ACK)。当消费者出现异常或者服务宕机时,MQ服务器不会删除该消息,而是会把消息重发给绑定该队列的消费者,如果该队列只绑定了一个消费者,则该消息会一直保持在MQ服务器,直到消费者能正常消费为止。


三、重复消费(重复消费、有序消费)

1.重复消费场景
原因:因消息重发机制会出现消息重复消费的情况

解决方案:
(1)幂等操作,同一个操作执行N次,结果不变。
(2)若实际业务中用不了幂等,则保存消息id到数据库(Redis)中,每次消费前查看消息是否已经被消费过。

2.有序消费场景
原因:在work queue模式下,只有一个队列,但存在多个消费者。多个消费者线程的竞争会导致数据乱序。在简单队列模式下,同样的多个消费者线程也会导致数据乱序。


解决方案:
(1)使用多个队列,对消息的id值做hash。再对队列数取模(hash值%队列数),将结果相同的消息压入同一个队列中去,这就保证了一个队列中有且仅有一个消费者。
(2)0在MQ队列后的Java代码中(消费方),再为每一个线程加一个内存队列,根据消息的id求hash值,然后把相同的结果压入同一个内存队列……

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表