消息积压

性能优化

性能的优化主要在生产者和消费者这俩业务逻辑

mq自身性能,作为API使用者,无需过度关注。因大多mq业务,mq本身处理能力远大于业务系统。主流mq的单个节点,消息收发性能可达几万到几十万条消息每秒,还可以水平扩展Broker实例数倍增处理能力。而一般业务系统需处理的业务逻辑远比消息队列复杂,单节点每秒可处理几百到几千次请求,性能已经算很好了。所以mq性能优化,更关注在消息收发两端,业务代码怎么和mq协作达到最佳性能

生产端

生产端业务代码处理性能实际上和mq关系不大,都是先执行自己的业务逻辑,最后再发送信息。如果你的代码发送消息的性能上不去,需要先检查是否因为发消息前的业务逻辑耗费太多时间导致。

对于发消息的业务逻辑,只需要注意设置合适并发和同步大小,即可达到很好发送性能。

这是因为Producer发消息给Broker,Broker收到消息后返回确认响应,这是一次完整交互。假设一次交互的平均时延是1ms,就算是单线程发送,每次只发1跳,则每秒只发1000条消息,这并不能压榨mq性能

无论是增加每次发送消息的批量大小,增加并发都能倍增发送性能,那么选择批量发送还是增加并发呢?

这取决于发送端的业务性质:

  • 如果发送端是个微服务,主要接受RPC请求处理在线业务。那么微服务在处理每次请求时,就在当前线程直接发消息即可,因为所有RPC框架都是多线程支持并发,自然可以并行发送消息,且在线业务比较在意请求响应时间。这时就可以通过并发提升发送性能更好
  • 如果是离线分析系统,并不关心时延,更关注整个系统的吞吐量,这时候用批量发送就更适合了

消费端

使用mq的时候,大部分性能问题都出现在消费端。如果消费速度跟不上发送端生产消息的速度,就会造成消息积压。如果这种性能倒挂问题只是暂时的,那还好,只要消费端的性能恢复之后,超过发送端的性能,那积压的消息是可以逐渐被消化掉的

若消费速度一直比生产速度慢。久而久之,系统就会异常,mq存储被填满无法提供服务或者消息丢失

所以设计系统,要保证消费端消费性能高于生产端发送性能,系统才能长治久安

消费端性能优化除优化消费业务逻辑,也可以水平扩容,增加消费端并发数提升总体消费性能。扩容consumer实例数和分区数量相等。若consumer实例数量大于分区数量,这样的扩容实际上徒劳。因为对消费者,在每个分区实际上只能支持单线程消费。

处理方法

消息积压突然增加,问题只有两种:

  • 要么发送变快
  • 要么消费变慢

这时候我们可以通过监控数据,很容易确定是哪种原因。如果是单位时间发送消息增多,比如说是赶上抢购,短时间内不太可能优化消费端代码提升性能,唯一方法通过扩容消费端实例数提升总体消费能力。如果短时间没足够服务器资源扩容,将系统降级,通过关闭一些不重要业务,减少发送方发送数据量,最低限度让系统还能运转,服务一些重要业务。

kafka不仅是扩容时候,只要是consumer和partition有一方的数量变化,都会触发rebalance

还有种不太常见的,通过监控发现,无论是发送消息速度还是消费消息速度和原来都没什么变化,这是需检查消费端,是不是消费失败导致的一条消息反复消费,也会拖慢整个系统消费速度。

如果监控到消费变慢,需要检查消费实例,分析一下是什么原因导致消费变慢。优先检查一下日志是否有大量消费错误,如果没有,可以打印堆栈信息,看消费线程是不是卡在什么地方不懂,比如触发死锁或卡在某些资源

如果消费者消费异常,即使多次消费也无法成功处理(如消息格式异常),导致一直无法成功ack此条消息,这种场景一般要怎么处理? 有的MQ提供了“死信队列”的功能,它会自动把这种反复消费都失败的消息丢到一个特殊的死信队列中,避免一条消息卡主队列情况。

总结

消息积压处理:

  1. 发送端优化,增加批量和线程并发两种方式处理
  2. 消费端处理,优化业务逻辑代码,水平扩容增加并发并同步扩容分区数量

查看消息积压的方法:

  1. 消息队列内置监控,查看发送端发送消息和消费端消费消息的速度变化
  2. 查看日志是否有大量的消费错误
  3. 打印堆栈信息,查看消费线程卡点信息
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐