目录
一、提前预防,通过优化性能的方式,来避免出现消息积压
消息队列处理能力能够达到每秒几万甚至几十万条消息的水平,而业务系统需要处理的业务逻辑比消息队列复杂,所以单个节点能够处理几百到几千的请求,就已经算是性能很好的了。因此,对于消息队列的性能优化,我们更关注的事,在消息的收发两端,我们的业务代码怎么和消息队列配合,达到一个最佳的性能。
1. 发送端性能优化
因为发送端一般都是要先执行自己的业务逻辑,然后再发送消息的,所以发送端发送消息的性能比较低,有可能是因为在发消息之前,执行业务逻辑耗时太长了。
(1)那要如何解决业务逻辑执行耗时过长这件事呢?
设置合适的并发和批量大小,就能够达到很好的发送性能。
(2)发送消息过程中需要考虑哪些步骤的耗时?
Producer
发送消息的过程,Producer
发消息给Broker
,Broker
收到消息后返回确认响应,这是一次完整的交互。假设这一次交互的平均时延时 1ms,我们把这 1ms 的时间分解开,它包括了下面这些步骤的耗时:
- 发送端准备数据、序列化消息、构造请求等逻辑的时间,也就是发送端在发送网络请求之前的耗时;
- 发送消息和返回响应在网络传输中的耗时;
- Broker 处理消息的时延。
如果是单线程发送,每次只发送1条消息,那么每秒只能发送 1000 ms / 1ms * 1条 / ms = 1000条消息,这种情况下并不能发挥出消息队列的全部实力。
那么我们就可以增加每次发送消息的批量大小,或者增加并发,从而成倍提升发送性能。至于到底是选择批量发送
还是增加并发
,主要取决于发送端程序的业务性质。简单来说,只要能够满足你的性能要求,怎么方便就怎么实现。
(3)举例
- 如果说你的消息发送端是一个
微服务
,主要接收 RPC 请求处理
在线业务。很自然的,微服务在处理每次请求的时候,就在当前线程
直接发送消息就可以了,因为所有 RPC 框架都是多线程支持多并发的,自然也就实现了并行发送消息
。并且在线业务比较在意的是请求响应时延
,选择批量发送
必然会影响 RPC 服务的时延
。这种情况,比较明智的方式就是通过并发
来提升发送性能。 - 对于一个离线分析系统来说,离线系统并不关心时延,更注重整个系统的吞吐量。发送端的数据都是来自于数据库,这种情况就
更适合批量发送
,你可以批量从数据库读取数据,
2. 消费端性能优化
如果消费速度一直比生产速度慢,时间长了,整个系统就会出问题。要么消息队列的存储被填满无法提供服务,要么消息丢失。
所以,我们在设计系统的时候,一定要保证消费端的消费性能要高于生产端的发送性能,这样的系统才能监控地持续运行。
如何提高消费端性能
- 优化消费业务逻辑
- 水平扩容,增加消费端的并发数来提高总体的消费性能
- 因为对于消费者来说,在每个分区(也叫队列)上只能支持单线程消费,所以扩容
Consumer
的实例数量的同时,也必须同步扩容主题中的分区数量,确保Consumer
的实例数和分区数是相等的。如果Consumer
的实例数量超过分区数量,这样的扩容实际上是没有效果的。
- 因为对于消费者来说,在每个分区(也叫队列)上只能支持单线程消费,所以扩容
- 将消息放到内存队列中,可以快速地返回响应,而处理消息的业务线程可以实现并行消费,提高系统的吞吐量和性能,解决了单个
Consumer
不能并行消费的问题。
二、线上系统出现了消息积压,如何紧急处理
1. 分析消息积压出现的原因
(1)关于消息积压的出现,最粗粒度的原因,只有两种:
- 消息发送变快了
- 系统消费的速度变慢了
(2)常见原因大致有如下三个:
- 任务产生的服务过多,任务处理的服务过少,不均衡;
- 任务处理时间太长,也导致生产过剩;
- 中间件本身容量偏小,需要扩容或集群化管理;
2. 解决问题
(1)对任务生成进行流量控制
(2)监控,扩容消费端实例
来提升总体的消费能力
(3)系统降级
,关闭一些不重要的业务,减少发送方发送的数据量
(4)消费变慢了,可以检查日志
,看看是否有大量消费错误;可以看看线程是不是卡在什么地方
不动,比如:等待某些资源或者触发死锁