Kafka 消费者组管理模块(一):组元数据与组成员元数据

        消费者组的元数据主要是由 GroupMetadata 和 MemberMetadata 两个类组成,它们分别位于 GroupMetadata.scala 和 MemberMetadata.scala 这两个源码文件中。从它们的名字上也可以看出来,前者是保存消费者组的元数据,后者是保存消费者组下成员的元数据。

MemberMetadata

先看 MemberMetadata.scala 文件,包括 3 个类和对象

  • MemberSummary 类:组成员概要数据,提取了最核心的元数据信息。
  • MemberMetadata 伴生对象:仅仅定义了一个工具方法,供上层组件调用。
  • MemberMetadata 类:消费者组成员的元数据。Kafka 为消费者组成员定义了很多数据,一会儿我们将会详细学习。

MemberSummary 类

        组成员元数据的一个概要数据类

case class MemberSummary(  memberId: String,                 // 成员ID,由Kafka自动生成
                           groupInstanceId: Option[String],  // Consumer端参数group.instance.id值,消费者组静态成员的 ID。
                           clientId: String,                 // client.id参数值
                           clientHost: String,               // Consumer端程序主机名
                           metadata: Array[Byte],            // 消费者组成员使用的分配策略
                           assignment: Array[Byte])          // 成员订阅分区)

MemberMetadata 伴生对象

        它只定义了一个 plainProtocolSet 方法,供上层组件调用。这个方法只做一件事儿,即从一组给定的分区分配策略详情中提取出分区分配策略的名称,并将其封装成一个集合对象。

private object MemberMetadata {
  // 提取分区分配策略集合
  // 如果消费者组下有 3 个成员,它们的 partition.assignment.strategy 参数分别设置成 RangeAssignor、RangeAssignor 和 RoundRobinAssignor,那么,plainProtocolSet 方法的返回值就是集合[RangeAssignor,RoundRobinAssignor]。
  def plainProtocolSet(supportedProtocols: List[(String, Array[Byte])]) = supportedProtocols.map(_._1).toSet
}

MemberMetadata 类

private[group] class MemberMetadata(var memberId: String,
                                    val groupId: String,
                                    val groupInstanceId: Option[String],
                                    val clientId: String,
                                    val clientHost: String,
                                    val rebalanceTimeoutMs: Int, // Rebalane操作超时时间,即一次 Rebalance 操作必须在这个时间内完成,否则被视为超时。
                                    val sessionTimeoutMs: Int, // 会话超时时间,当前消费者组成员依靠心跳机制“保活”。如果在会话超时时间之内未能成功发送心跳,组成员就被判定成“下线”,从而触发新一轮的 Rebalance。
                                    val protocolType: String, // 对消费者组而言,是"consumer",还有"connect"
                                    var supportedProtocols: List[(String, Array[Byte])]  // 分区分配方案
                                   ) {

  var assignment: Array[Byte] = Array.empty[Byte] // 保存分配给该成员的分区分配方案。
  var awaitingJoinCallback: JoinGroupResult => Unit = null // 表示组成员是否正在等待加入组。
  var awaitingSyncCallback: SyncGroupResult => Unit = null // 表示组成员是否正在等待 GroupCoordinator 发送分配方案。
  var isLeaving: Boolean = false // 表示组成员是否发起“退出组”的操作。
  var isNew: Boolean = false // 表示是否是消费者组下的新成员。
  val isStaticMember: Boolean = groupInstanceId.isDefined

  // This variable is used to track heartbeat completion through the delayed
  // heartbeat purgatory. When scheduling a new heartbeat expiration, we set
  // this value to `false`. Upon receiving the heartbeat (or any other event
  // indicating the liveness of the client), we set it to `true` so that the
  // delayed heartbeat can be completed.
  var heartbeatSatisfied: Boolean = false

  def isAwaitingJoin = awaitingJoinCallback != null
  def isAwaitingSync = awaitingSyncCallback != null
}

       其中的metadata方法从该成员配置的分区分配方案列表中寻找给定策略的详情。

  def metadata(protocol: String): Array[Byte] = {
    // 从配置的分区分配策略中寻找给定策略
    supportedProtocols.find(_._1 == protocol) match {
      case Some((_, metadata)) => metadata
      case None =>
        throw new IllegalArgumentException("Member does not support protocol")
    }
  }

组元数据(GroupMetadata 类)

private[group] class GroupMetadata(val groupId: String,  // 组ID
                                   initialState: GroupState, // 消费者组初始状态
                                   time: Time) extends Logging {
  type JoinCallback = JoinGroupResult => Unit

  private[group] val lock = new ReentrantLock
  // 定义了消费者组的状态空间。当前有 5 个状态,
  // Empty 表示当前无成员的消费者组;
  // PreparingRebalance 表示正在执行加入组操作的消费者组;
  // CompletingRebalance 表示等待 Leader 成员制定分配方案的消费者组;
  // Stable 表示已完成 Rebalance 操作可正常工作的消费者组;
  // Dead 表示当前无成员且元数据信息被删除的消费者组。
  private var state: GroupState = initialState
  // 记录状态最近一次变更的时间戳,用于确定位移主题中的过期消息。
  // 位移主题中的消息也要遵循 Kafka 的留存策略,所有当前时间与该字段的差值超过了留存阈值的消息都被视为“已过期”(Expired)。
  var currentStateTimestamp: Option[Long] = Some(time.milliseconds())
  var protocolType: Option[String] = None
  // 消费组 Generation 号。Generation 等同于消费者组执行过 Rebalance 操作的次数,每次执行 Rebalance 时,Generation 数都要加 1。
  var generationId = 0
  // 记录消费者组的Leader成员,可能不存在
  // 消费者组中 Leader 成员的 Member ID 信息。当消费者组执行 Rebalance 过程时,需要选举一个成员作为 Leader,负责为所有成员制定分区分配方案。
  // 在 Rebalance 早期阶段,这个 Leader 可能尚未被选举出来。这就是,leaderId 字段是 Option 类型的原因。
  private var leaderId: Option[String] = None
  private var protocol: Option[String] = None
  // 成员元数据列表信息
  private val members = new mutable.HashMap[String, MemberMetadata]
  // Static membership mapping [key: group.instance.id, value: member.id]
  // 静态成员Id列表
  private val staticMembers = new mutable.HashMap[String, String]
  private val pendingMembers = new mutable.HashSet[String]
  private var numMembersAwaitingJoin = 0
  // 分区分配策略支持票数
  private val supportedProtocols = new mutable.HashMap[String, Integer]().withDefaultValue(0)
  // 保存消费者组订阅分区的提交位移值
  private val offsets = new mutable.HashMap[TopicPartition, CommitRecordMetadataAndOffset]
  private val pendingOffsetCommits = new mutable.HashMap[TopicPartition, OffsetAndMetadata]
  private val pendingTransactionalOffsetCommits = new mutable.HashMap[Long, mutable.Map[TopicPartition, CommitRecordMetadataAndOffset]]()
  private var receivedTransactionalOffsetCommits = false
  private var receivedConsumerOffsetCommits = false

  // When protocolType == `consumer`, a set of subscribed topics is maintained. The set is
  // computed when a new generation is created or when the group is restored from the log.
  // 消费者组订阅的主题列表
  private var subscribedTopics: Option[Set[String]] = None

  var newMemberAdded: Boolean = false
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值