一、背景
自2023年3月初上线新版计费以来,新版计费公司占比逐步增加,同时计费数据量和并发量也变大,因此计费结算业务逐渐存在一些性能隐患,经过长达半年的计费消息优化之后终于稳定下来,本文讲阐述计费消息消费的性能优化过程。
二、优化&迭代
2.1 同步消费(第一版)
第一版本代码如下,经过测试环境压测之后每条消息消费处理耗时约20ms,也就是说单机并发消费约50条/s.
@Override
public void run() {
try {
while (!closed.get()) {
try {
ConsumerRecords<String, BillLogEvent> records =
consumer.poll(Duration.ofSeconds(1000));
for (ConsumerRecord<String, BillLogEvent> record : records) {
//消费逻辑
exeConsume(record));
}
} catch (Exception e) {
try {
Thread.sleep(1000);
} catch (Throwable ignore) {
}
log.error("process error ",e);
}
}
} catch (WakeupException e) {
if (!closed.get()) {
log.error(e.getMessage(), e);
}
} finally {
consumer.close();
}
}
2.2 消息路由策略(第二版)
根据线上kafka分区的情况来看,总有1台机器对应的分区存在消息延迟,且消息堆积比较大,延迟大概10-20分钟。因此专门看了下kafka消息路由相关的内容:1.设置分区配置
ProducerConfig.PARTITIONER_CLASS_CONFIG
2.在发送消息的时候指定分区
根据计费的业务场景需要制定合适的分区策略,首先要满足的需求是分区消息要均匀,因此设计如下方案
-
按时间戳进行随机分区 -
按公司ID进行hash分区 -
按随机数进行分区
经过第一次讨论使用的是按时间戳进行随机分区,但是线上观察后仍然有问题,因此进行了2.3的优化
2.3 直接消费策略+多线程消费(第三版)
经过上面的分区改造实际上仍然无法满足逐渐增长的日均计费消息量,因此消息消费能力也需要提升。在这一版本中修改了消息分区的策略,使用按公司ID进行hash分区,同时在发送消息的时候指定分区ID。
-
直接消费策略
之前因为消息堆积问题,导致部分手动扣费场景产生的计费消息在kafka分区里无法快速消费,业务上感知比较明显,业务重试的话就会产生多次扣费,因此为了避免消息堆积的问题,梳理了部分手动扣费的场景,并在计费网关接口上进行改造。流程如下:
-
多线程消费
就是将消费逻辑的方法用多线程处理下:
//线程池处理
consumeTaskExecutor.execute(()-> exeConsume(record));
2.4 优化结果
经过上述的优化方案落地后,线上运行的效果如下:
-
延迟基本不再敏感,各个分区堆积只有20-40条左右 -
业务操作消息直接消费,不影响计费 -
测试环境压测可单节点处理200条消息/每秒,线上的情况跟进约单节点处理70条消息/每秒。
三、总结
经过持续不断的计费消息优化,可以了解到如下几点:
-
优化要考虑结合业务 -
优化要有针对性 -
优化要做数据摸底和数据支撑 -
优化前后要观察和总结
原文始发于微信公众号(神帅的架构实战):kafka 消息不均衡问题解决案例
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/241322.html