Kafka源码阅读 —— KafkaController(1)

KafkaController 启动

在KafkaServer.startup()中,KafkaController对象被构建,在启动KafkaApis、replicaManager后,KafkaController.startup()被调用。Kafka集群中每个Broker都会调用startup()函数,但是一个集群只有一个Broker能够成为Controller。那么,谁将成为这个被选中的人呢?
startup()函数非常简单,这里直接粘代码:

 def startup() = {
    inLock(controllerContext.controllerLock) {
      info("Controller starting up");
      registerSessionExpirationListener()
      isRunning = true
      controllerElector.startup
      info("Controller startup complete")
    }
  }

除去日志以及标识状态的isRunning赋值,值得看的代码就两句。其中registerSessionExpirationListener()用于在zookeeper会话失效后重连时取消注册在zookeeper上的各种Listener,而controllerElector.startup则启动了选举,这些都将发生在ZookeeperLeaderElector类中。
ZookeeperLeaderElector.elect函数负责选举leader,KafkaController选举是直接通过zookeeper实现的,就是在zookeeper创建临时目录/controller/并在目录下存放当前brokerId。如果在zookeeper下创建路径没有抛出ZkNodeExistsException异常,则当前broker成功晋级为Controller。除了调用elect外,controllerElector.startup还会在/controller/路径上注册Listener,监听dataChange事件和dataDelete事件,当/controller/下数据发生变化时,表示Controller发生了变化;而因为/controller/下的数据为临时数据,当Controller发生failover时,数据会被删除,触发dataDelete事件,这时就需要重新选举新一任Controller。


成为KafkaController

成为KafkaController之后很重要的一件事,就是在zookeeper各个关键路径上添加Listener,所以这里很有必要先总结一下跟controller相关的路径([ ]表示其中的值是随实际情况变化的):

  • /controller/{“brokerid”:”1”}: 决定谁才是这一届Controller,路径下存放当前Controller的brokerId,这些信息以临时数据的形式存放,在会话失效时会被删除。类LeaderChangeListener监听该路径下的dataChange和dataDelete事件。
  • /brokers/topics:子目录为所有topic列表。类TopicChangeListener监听子目录列表变化,如果有新增topic,则调用onNewTopicCreation创建新的topic。
  • /brokers/topics/[topic]/:存放的是topic下各个分区的AR,目录下存放的格式为{“partitions”:{“partitionId1”:[broker1,broker2], …}}。类AddPartitionsListener监听路径下的数据变化,在有新增partition时调用Controller.onNewPartitionCreate,即创建新的partition。
  • /brokers/topics/[topic]/partitions/[partitionId]/state/:存放的是各个分区的leaderAndIsr信息,即各个分区当前的leaderId,以及ISR。类ReassignedPartitionsIsrChangeListener监听该路径下的数据变化,在重新分配replica到partition时,需要等待新的replica追赶上leader后才能执行后续操作。
  • /brokers/ids/[brokerId]/brokerInfoString:存放broker信息,brokerInfoString包括broker的IP,端口等信息;BrokerChangeListener监听/brokers/ids/下子目录变化,从而通知Controller broker的上下线消息。brokerInfoString是Controller判断的broker是否活着的条件之一,controllerContext中的liveBrokers需要相应路径下能够获取到brokerInfo。
  • /admin/reassign_partitions:指导重新分配AR的路径,通过命令修改AR时会写入到这个路径下。类PartitionsReassignedListener监听该路径下的内容变化,调用initiateReassignReplicasForTopicPartition,执行重新分配AR操作。
  • /admin/preferred_replica_election:分区需要重新选举第一个replica作为leader,即所谓的preferred replica。类PreferredReplicaElectionListener监听该路径,并对路径下的partitions执行重新选举preferred replica作为leader。

进入正题,成为KafkaController以后,会执行什么操作呢?
1. 升级Controller Epoch,并将新的epoch写入到zookeeper中;新的epoch标识着下一个世代的leader,向其他broker发送命令时会校验epoch;
2. 监听zookeeper路径/admin/reassign_partitions;
3. 监听zookeeper路径/admin/preferred_replica_election;
4. 注册partition状态机中的监听器,监听路径/brokers/topics的子目录变化,随时准备创建topic;
5. 注册replica状态机中的监听器,监听路径/brokers/ids/的子目录,以便在新的broker加入时能够感知到;
6. 初始化ControllerContext,主要是从zookeeper中读取数据初始化context中的变量,诸如 liveBrokers,allTopics,AR,LeadershipInfo等;
7. 初始化ReplicaStateMachine,将所有在活跃broker上的replica的状态变为OnlineReplica;
8. 初始化PartitionStateMachine,将所有leader在活跃broker上的partition的状态设置为Onlinepartition;其他的partition状态为OfflinePartition。Partition是否为Online的标识就是leader是否活着;之后还会触发OfflinePartition 和 NewPartition向OnlinePartition转变,因为OfflinePartition和NewPartition可能是选举leader不成功,所以没有成为OnlinePartition,在环境变化后需要重新触发;
9. 在所有的topic的zookeeper路径/brokers/topics/[topic]/上添加AddPartitionsListener,监听partition变化;

完成对各个zookeeper路径的监听后,zookeeper内容的变化驱动Controller进行各种操作,处理如新建topic,删除topic,broker失效,broker恢复等事件。

Controller Failover

前面startup()中registerSessionExpirationListener()会注册会话监听器,在zookeeper会话过期后又重连成功时调用onControllerResignation(),并重新执行选举操作。
此外,当Controller会话失效时,会删除/controller/路径下创建的临时数据。与此同时,其他broker上的ZookeeperLeaderElector类中的LeaderChangeListener感知到数据删除后会重新执行选举。
onControllerResignation()是Controller转变为普通broker时执行的操作,就是将前面注册的各个Listener取消注册,不再关注zookeeper变化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值