一、技术背景
在我们的日常项目中,Kafka是一项很常用的技术,我们可以用来做MySql + Cancel + Kafka实现数据库表的监听,实现具体的一些逻辑。同样Kafka也是一款高吞吐、高性能的消息中间件。具体的Kafka的技术相关事项就不在这里多做赘述。
二、业务背景
我这次的业务是基于某个一个订单在执行完业务逻辑后将执行完成的消息发送到Kafka,异步执行后置的逻辑。
三、技术设计方案图
由于具体的业务并不在此处讨论的范围内,所以利用通用的案例来进行记录。
如图技术方案设计图所示,具体的业务是一个Kafka消费者里面再发一个Kafka消息的情况,姑且把他称为Kafka消费者嵌套。
四、出现问题的原因
1、由于组内新团队成员不太清楚部门的一些Kafka使用规则,以及在使用过程中的不细心,在创建tobic-B的时候只创建了6个分区,然后在发送端(生产者)直接复制以前的发送代码,以前的发送代码为了生产环境的10个节点考虑,都是建立10个分区,所以是用10分区数来做一致性哈希算法来决定发送到Kafka的具体的分区上。所以导致产生的情况是如果算出来要发到6-9分区的时候,分区不存在导致的发送卡顿,根据kafka的默认配置是60s超时。
2、又因为这里的场景设计是消费者嵌套消费者,topic-A是批量拉取50条进行消费,部分数据要发到topic-B的6-9分区时,去到服务器看发现在topic-A端报60s发送超时
Topic topic-B not present in metadata after 60000 ms
这个60s是可以通过参数max.block.ms进行控制,
默认是60s,但是我们出现问题的时候也不要指望把这个调小就可以解决问题,本质上还是要解决为什么这个消息在生产者处会发送超时。
继续刚才的流程,topic-A发送消息给topic-B时找不到topic-B分区时,会等待60s然后超时,这里会严重影响topic-A的性能,从而导致topic-A的消费者在规定的5分钟内并没有消费完50条消息,所以导topic-A消费组发送重平衡了,重平衡以后到另一个消费者同理,又再次重平衡,导致整个topic-A消费者瘫痪,topic-A出现消息挤压以及重平衡。
五、解决方案
1、直接找到运维将topic-B的分区数新增到10个分区,让算法算出来的分区数都能够发送到对应的分区。打包重新发布,topic-A堆积的消息开始消费。
六、总结
1、尽量避免kafka消费者嵌套消费者的情况,防止消费者雪崩现象的发生。
2、kafka可以通过两个参数去控制消费时长
-
max.poll.interval.ms:拉取下来多少时间内消费完成
-
max-poll-records :一次性拉取多少条进行消费
如果生产环境出现消费者因为消费慢的原因出现重平衡现在,实在没有排查出具体原因导致消费慢的情况下,可以适当的增大max.poll.interval.ms,以及减少max-poll-records的值去解决问题,不过不是根本的解决方式,还是要找到消费慢的地方进行优化。