Go操作Kafka关键在客户端选型、配置项取值和资源释放时机:kafka-go适合简单场景,sarama适合需严格语义的生产环境;须设RequiredAcks、显式调用Close()、合理配置offset提交策略及advertised.listeners。

Go 操作 Kafka 不难,但默认配置下极容易丢消息、连不上、消费卡死——关键在客户端选型、配置项取值和资源释放时机。
sarama 和 kafka-go 怎么选
别被 star 数带偏。segmentio/kafka-go 简洁,但 Reader 默认不支持消费者组自动重平衡;Shopify/sarama 重一点,但 ConsumerGroup 实现完整,适合需 at-least-once 语义的生产环境。
- 单分区、快速验证、本地调试:用
kafka-go,WriteMessages一行发,ReadMessage一行收 - 对接已有集群、要 SSL/SASL/精确 offset 控制/消费者组:选
sarama,尤其注意它不自动关连接,Close()必须显式调用 - 别在
init()里全局初始化sarama.SyncProducer—— 它不是线程安全的,高并发下直接 panic
sarama 生产者必须设的三个配置
NewSyncProducer 听起来可靠,但成功返回 ≠ 消息已落盘。Broker 默认配置下,RequiredAcks = sarama.NoResponse,发完就返回,broker 甚至没写入页缓存。
- 必须设
config.Producer.Return.Successes = true,否则你根本不知道消息发到了哪个partition和offset -
config.Producer.RequiredAcks = sarama.WaitForAll(即acks=-1),但前提是 topic 的replication-factor >= 2,否则会退化为只等 leader - 必须显式调用
producer.Close(),否则 goroutine 泄露 + TCP 连接堆积,broker 日志会出现Connection reset
kafka-go 消费者为什么卡住
ReadMessage 默认阻塞,但卡住往往不是 Kafka 问题,而是 offset 提交策略不当。
- 每条都立刻
CommitMessages:吞吐暴跌,RTT 成瓶颈;且提交后 crash,消息会被重复消费 - 完全不提交、只靠
AutoCommit: true:consumer 重启后从上次自动保存位置开始,可能跳过未处理完的消息 - 推荐做法:批量处理 10–100 条后手动
CommitMessages,同时用context.WithTimeout包裹ReadMessage,防无限阻塞
本地连不上 localhost:9092?先看 advertised.listeners
Docker 或远程 client 连不上,90% 是 broker 的 advertised.listeners 配置错了。Kafka broker 默认监听 localhost,但 client 会按 advertised.listeners 里的地址去连——如果它还是 localhost,就会连错。
- 本地开发:把
advertised.listeners设成PLAINTEXT://127.0.0.1:9092 - Docker 部署:设成宿主机可访问的 IP 或域名,比如
PLAINTEXT://host.docker.internal:9092 - 改完必须重启 broker,且确认
listeners和advertised.listeners地址能互相解析
最常被忽略的是:sarama 的 Close() 调用时机、kafka-go 的批量 commit 粒度、以及 advertised.listeners 和实际网络拓扑的匹配——这三个点一错,问题就藏得深,日志里还看不出明显报错。



















