Skip to main content

最佳实践

资源分配管理

建议 1: 合理设置 Topic 分区数,避免吞吐瓶颈以及浪费

Kafka Topic 分区数影响了 Topic 能够支持的生产和消费吞吐,在保证顺序的前提下,相同分区 Key 的消息发送到同一个分区,并且 Kafka 每个分区只能被一个消费者处理。

AutoMQ 基于对象存储构建,相比于 Apache Kafka 本地文件的架构,相同的集群规模下可以支持数十倍的分区性能。同时 AutoMQ 对分区不收费。

使用 AutoMQ 分配分区时,无需为成本考虑,只需要按照业务预估的分区吞吐性能评估合适的分区数(AutoMQ 单个分区写入吞吐上限为 4MB/s ),避免后期业务上量再扩展分区。分区数也无需和节点数量的倍数关联,AutoMQ 会自动实现分区的均衡。

举例:

某应用预估未来 1年内 Topic 数据写入吞吐大概是 100MB/s,同时下游消费者单个消费者每秒最多只能处理 2MB 的数据。

则分配分区时需要考虑:

基于生产者视角,需要 100MB/s ÷ 4MB/s = 25 个分区。

基于消费者视角,需要 100MB/s ÷ 2MB/s = 50 个消费者,50 个消费者至少需要 50 个分区。

因此,需要分配至少 50 个分区才可以满足应用的需求。

建议 2: 平台类应用场景,建议开启 ACL,实现上下游访问强管控,便于后期梳理链路拓扑

平台类场景,例如实时计算平台,使用 Kafka 时建议开启 ACL 实现资源细粒度管控。开启资源管控后Kafka 客户端必须进行身份校验才能访问特定的 Topic、Group。这样做有如下好处:

  • 避免业务方随意创建新的 Topic 等资源,造成资源滥用,无法治理。

  • 可以规避不同业务方混用 Consumer Group 造成订阅混乱,影响消费负载均衡。

  • 根据 Topic、Consumer Group 就可以找出相关的订阅方和上下游业务组,方便进行业务治理。

生产者应用

建议 1:客户端小于 2.1 版本 Kafka Producer 建议设置重试次数

生产者应用需要检查 SDK 版本,如果当前版本小于 2.1,则需要手工设置重试次数,确保消息发送失败时可以自动重试,避免因服务端运维、自动分区迁移等场景造成失败。

重试参数设置可以参考如下信息:


//最大重试次数
retries=Integer.MAX_VALUE

//初始退避延迟时间。
retry.backoff.ms=100

//最大退避延迟时间。
retry.backoff.max.ms=1000

//每次发送请求的 RPC 超时时间
request.timeout.ms =30000

//整个发送调用整体超时时间,超过这个时间后即不再重试,返回调用侧失败异常。
delivery.timeout.ms=120000

建议 2: 优化 Producer 攒批参数,避免碎请求消耗过多 QPS

Kafka 是面向高吞吐场景设计的流存储系统,Kafka 最典型的使用场景是通过批处理提升数据收发过程的效率和吞吐。在 Producer 发送消息过程中需要合理设置攒批参数,避免出现以下情况:

  • 避免每次请求只发送一条消息: 生产者每次只发送一条消息会造成大量的 Produce 请求,消耗服务端 CPU,造成集群性能下降。

  • 避免设置过长的攒批等待时间: 生产者在设置批量参数时需要设置合理的等待时长,避免因小流量场景下一直无法攒批完成,造成发送消息延迟。

具体设置攒批的参数参考下方:


//批量大小,一次性最多积累128KB 的数据。
batch.size=131072
//攒批时间,对于生产者,如果在指定的时间内没有达到攒批的上限,也会触发发送,这个时间代表了发送的最大延迟。
linger.ms=10

消费者应用

建议 1: 注意 Assign 模式消费者,建议升级到 3.2 及以上版本,确保消费位点提交成功率

Kafka Consumer 应用在消费消息时,如果使用了 Assign 模式,即自行分配分区负载均衡的模式,需要确保 SDK 版本升级到 3.2 及以上版本。因为早期版本在 Assign 模式下会存提交消费位点的缺陷,导致消费者位点无法及时提交和更新。详细的缺陷记录参考 Kafka Issue-12563

建议 2:合理控制 Consumer 心跳超时时间以及单次 poll 消息数量,避免频繁 Rebalance

Kafka Consumer 之间通过相同的 Group Id 进行分组和负载均衡,如果单个消费者出现了心跳超时,则会被驱逐出消费者分组,剩余的消费者会重新进行 Rebalance,分配分区。

在生产场景下,应该避免程序参数错误导致非预期的心跳超时和 Rebalance,否则会导致消费者分组一直变化无法消费消息。

触发非预期 Rebalance 的原因:

  • v0.10.2之前版本的客户端:Consumer 没有独立线程维持心跳,而是把心跳维持与 poll 接口耦合在一起。其结果就是,如果用户消费出现卡顿,就会导致 Consumer 心跳超时,引发Rebalance。

  • v0.10.2及之后版本的客户端:如果消费时间过慢,超过一定时间(max.poll.interval.ms设置的值,默认5分钟)未进行poll拉取消息,则会导致客户端主动离开队列,而引发Rebalance。

优化建议:

将客户端升级至0.10.2以上版本。

参考以下说明调整参数值:

尽量提高客户端的消费速度,避免卡顿。

尽量避免一个 Group 订阅大量 Topic 的情况,做到专属 Group 订阅专属 Topic。

建议 3:生产场景建议提交消费位点,但不要高频率提交位点

使用 Kafka 消费消息时,无论使用普通的 Kafka Consumer SDK,还是使用 Flink Connector 等框架,都建议提交消费位点,这样可以观测消费堆积,避免风险。

提交消费位点有两种方式,一种是自动提交,一种是手动提交。控制的参数是:

  • enable.auto.commit :是否采用自动提交位点机制。默认值为true,表示默认采用自动提交机制。

  • auto.commit.interval.ms : 自动提交位点时间间隔。默认值为1000,即1s。

这两个参数组合的结果就是,每次poll数据前会先检查上次提交位点的时间,如果距离当前时间已经超过参数auto.commit.interval.ms 规定的时长,则客户端会启动位点提交动作。

因此,如果将enable.auto.commit 设置为true,则需要在每次poll数据时,确保前一次poll出来的数据已经消费完毕,否则可能导致位点跳跃。

如果想自己控制位点提交,请把enable.auto.commit 设为false,并调用commit(offsets)函数自行控制位点提交。

生产场景下,建议一定要提交位点,但不要高频率的提交消费位点。否则会导致处理消费位点的 Compact Topic 分区出现请求热点。

生产场景下建议根据需求,一般 5-10 秒定时或者手工提交即可,不需要每次消费消息都提交位点。

建议 4:生产场景避免消费阻塞导致堆积

Kafka 消费者按分区顺序处理消息,如果某条消息因业务逻辑导致消费阻塞,会影响当前分区后续消息的消费。因此生产环境中应确保消费逻辑处理不会永久阻塞。

如果出现非预期的阻塞情况,建议按以下流程处理:

  • 判断是否可以跳过: 如果可以跳过该异常消息,则可以先停止消费者,前往 AutoMQ 控制台重置消费位点到下一条消息,实现跳过处理。

  • 判断不可跳过: 修复消费逻辑,处理该异常消息。

使用 Flink Connector 消费 Kafka 消息时,需要注意 Flink Connector 版本,建议升级到 1.17.2 及以上版本。因为早期的 Flink Connector 版本依赖了更早版本的 Kafka SDK,这些版本在提交消费位点时如果遇到失败则无法重试,这会导致 Flink 任务的 Consumer Group 在 Kafka 产品里无法准确观测堆积数指标。详细的缺陷记录参考 Kafka Issue-12563