问题剖析
最近把 Kafka-Storm-Hbase 做了一个集成,然后发现了一个问题就是 Kafka 消息队列的消费贼慢。
网上好像没有这个相关的问题,我来分享一下我的实战经验咯。
我的 KafkaSpout 配置是这样的:
private static KafkaSpoutConfig<String, String> newKafkaSpoutConfig() { return KafkaSpoutConfig.builder("172.16.3.82:9092,172.16.3.83:9092,172.16.3.84:9092", "test-topic") .setProp(ConsumerConfig.GROUP_ID_CONFIG, "kafkaSpoutTestGroup") .setProp(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, 2048) .setMaxUncommittedOffsets(250) .build(); }
其中有一个参数是:setMaxUncommittedOffsets(250),为什么他妈的是 250 呢?网上好多人都用这个参数,你们良心不会痛吗?
那么这个参数的默认值是多少呢?
默认值是:1000W。
这个参数我知道啥意思,但是为什么设置 250 就会慢呢?
原因是它和另外一个参数有关:offset.commit.period.ms,这个参数是控制多久向 Kafka commit 一次。
maxUncommittedOffset = 250 的执行过程是这样的:
- 当我们消费了 250 条消息之后,达到了 maxUncommittedOffset,这个时候客户端(Kafka Spout)已经不能再 poll 了,它要等待 commit;
- 此时 commit 的默认周期是 30000 ms(也就是 30 秒钟提价一次),这他妈意味着如果不改 commit 的周期,你 30s 只能消费 250 条。
真他妈会设置参数,250,250 你个头!!!
提示:了解运作原理对于调优和排查问题非常有必要,其实都不难,关键是除了问题你能否马上解决。
Kafka Spout 性能调优
Kafka spout 提供了两个内部参数来控制它的性能。这些参数可以用 setOffsetCommitPeriodMs 和 setMaxUncommittedOffsets 方法来设置。
- "offset.commit.period.ms" 控制 spout 多久向 Kafka 提交一次
- "max.uncommitted.offsets" 控制在下一个 poll 发生之前有多少偏移量可以等待提交
Kafka 消费者配置参数也会对 spout 的性能有影响。下面几个参数对 spout 性能的影响最大:
- "fetch.min.bytes"
- "fetch.max.wait.ms"
- Kafka 消费者实例的 poll 超时时间,对每一个 Kafka spout 用 setPollTimeoutMs 方法进行设置
根据你的 Kafka 集群的结构,数据的分布,以及待 poll 数据的可用性,这些参数需要正确的配置。请参考关于 Kafka 参数调优的 Kafka 文档。
默认值
目前 Kafka spout 有如下的默认值,在测试环境下有不错的性能:
- poll.timeout.ms = 200
- offset.commit.period.ms = 30000 (30s)
- max.uncommitted.offsets = 10000000