「Golang kafka客户端sarama源码分析」 1. ConsumerGroup源码分析开篇

3,871 阅读4分钟

开篇

去年抽出业余时间阅读了sarama源码,近期心血来潮想把之前的阅读笔记整理成文。仅做抛砖引玉,与大家交流分享。本次专题源码分析所使用的sarama版本为v1.41.1

在阅读本专题前,需要对 Kafka 有一些基本了解,对于一些 Kafka 相关的知识,不做过多介绍。另外,在分析过程中,我会尽量做到主线与细节之间的平衡,在讲清楚主线的同时,适当对细节进行介绍。让大家对sarama的工作机制有一个清晰的整体认识。剩下的细节,大家有兴趣就可以自行研究了。

本次专题,我们先从ConsumerGroup这部分开始。

架构总览

sarama_consumer-导出 (2).png

成员浅析

我们首先对架构图中的每个成员做简要介绍,在后续篇章中,会对它们的工作做详细介绍。

  • ConsumerGroup:sarama消费者组对象,调用它提供的Consumer方法,即可开始拉取消息进行消费

  • ConsumerGroupSession:用于控制消费者组的会话:

    • 它可由用户在调用 ConsumerGroup.Consumer 时传入的 context 结束会话。
    • 初始化完成时会启动一个循环向 Kafka 集群发送心跳消息保证消费者的存活。
    • 在发生消费者组reblance时,结束消费,进行消费者订阅的重新分配。
    • 执行用户层回调函数
  • ConsumerHandler:sarama中提供的一个叫做 ConsumerGroupHandler 的interface,它提供了 Setup(启动),Cleanup(结束)和ConsumeClaim(消费)三种(回调)方法。用户根据自身业务需要编写实现 ConsumerGroupHandler,并传入 ConsumerGroup 中。当 ConsumerGroupSession 初始化完成后,会调用 Setup 和 ConsumeClaim 方法。ConsumerHandler 就是 ConsumerGroupHandler 的实现类型。

  • ConsumerGroupClaim:ConsumerGroupClaim代表对一个 Topic/Partition 的订阅。它可以理解为是底层和 ConsumerHandler 之间的信使,向用户开放消息处理的通道。在 ConsumerHandler的ConsumeClaim 回调方法中调用ConsumerGroupClaim的 Messages 方法,该方法返回一个带有新拉取的消息的 channel ,给用户处理消息。

  • Consumer:sarama消费者实例,在创建 ConsumerGroup 实例时一同创建。它并不参与实际的消费,而是管理着 partitionConsumer 和 brokerConsumer 的对应关系。二者关系可看架构图。

  • partitionConsumer:它是 ConsumerGroupClaim 的下级,同样代表了一个 Topic/Partition 的订阅,它和 brokerConsumer 通过 channel 交互,读取拉取到的消息。ConsumerGroupClaim 中的 Messages 方法就是由其实现的。

  • brokerConsumer:每个 brokerConsumer 实例管理着多个 Topic/Partition 订阅。一个 brokerConsumer 下的所有 Topic/Partition 订阅,它们的分区 leader 位于 Kafka集群的同一个Broker中。

  • Client: Kafka客户端,在创建时需要传入Kafka集群的Broker地址列表。它负责生成并管理多个Broker实例,每个 Broker 实例维护着和制定Kfaka集群的Broker的TCP连接。

  • Broker: sarama的Broker对象,封装了 Kafka API,它负责真正和Kafka服务端交互。每个 Broker 实例维护着和指定Kafka集群的Broker的TCP连接。

入口

本次源码分析的入口代码就是官方提供的 Consumergroup 模版代码,位于sarama源码根目录下的 examples/consumergroup/main.go。模版代码并不复杂,这里根据代码执行顺序,简要介绍一下关键部分。

首先,调用 sarama.NewConsumerGroup 生成 ConsumerGroup 的实例

企业微信截图_42a45522-812c-4599-be30-5cbdcebda0b8.png

其次,调用 ConsumerGroup 的 Consume 方法开始进行消费(调用该方法时会传入ConsumerGroupHandler interface的实现类型的实例)。

这里会阻塞并监听的 consumer.ready 通道,当通道关闭或者读取到消息时,阻塞结束。

这个 consumer 实例是 ConsumerHandler 实例化后的对象。ConsumerHandler 就是用户对 ConsumerGroupHandler interface 的实现类型。ready channel 会在 ConsumerGroupSession 初始化后(此时代表消费者组的分区订阅分配完成,可以开始进行消费)通过 ConsumerHandler.Setup 方法进行回调。

在完成 consumer.ready 的阻塞监听后,通过一个 for 循环监听 context 取消和操作系统信号。保证消费者程序正常退出。 企业微信截图_48e5227b-b5b5-4a07-a77e-9e8f974d4157.png 企业微信截图_2a52a346-4e03-427e-8dc4-2425c4ac1ec5.png

ConsumerGroupHandler interface 的实现类型 ConsumerHandler 中同样也定义了 ConsumeClaim 方法。这个方法在每次 ConsumerGroupSession 初始化后会调用。持续监听处理消费者消费的消息。 企业微信截图_15c2100b-3daf-4264-9565-22a56d796000.png

总结

本章作为开篇对sarama的Consumergroup源码进行了架构简介和入口代码的分析。下一篇会沿着入口代码,逐步深入介绍 ConsumerGroupSession 和 ConsumerGroupClaim 等其他成员的工作机制。如有错误请广大掘友指正。