kafka 2.8 如何选择启用kraft还是ZooKeeper(选择逻辑源码,不涉及到kraft的实现)

这里用kakfa 3.0版本做源码演示

首先看一下kafka-server-start.sh 中的最后一行

exec $base_dir/kafka-run-class.sh $EXTRA_ARGS kafka.Kafka "$@"

我们知道了执行的是core/src/main/scala/kafka/Kafka.scala下的main方法

def main(args: Array[String]): Unit = {
    try {
      //获得配置文件中的参数
      val serverProps = getPropsFromArgs(args)
      //build server,非常重要,因为你要确定到底执行的是哪种server
      val server = buildServer(serverProps)

      try {
        if (!OperatingSystem.IS_WINDOWS && !Java.isIbmJdk)
          new LoggingSignalHandler().register()
      } catch {
        case e: ReflectiveOperationException =>
          warn("Failed to register optional signal handler that logs a message when the process is terminated " +
            s"by a signal. Reason for registration failure is: $e", e)
      }

      // attach shutdown handler to catch terminating signals as well as normal termination
      //附加关闭处理程序以捕获终止信号以及正常终止
      Exit.addShutdownHook("kafka-shutdown-hook", {
        try server.shutdown()
        catch {
          case _: Throwable =>
            fatal("Halting Kafka.")
            // Calling exit() can lead to deadlock as exit() can be called multiple times. Force exit.
            Exit.halt(1)
        }
      })
      //执行server的 startup
      try server.startup()
      catch {
        case _: Throwable =>
          // KafkaServer.startup() calls shutdown() in case of exceptions, so we invoke `exit` to set the status code
          //KafkaServer.startup() 调用 shutdown() 以防异常,所以我们调用 `exit` 来设置状态码
          fatal("Exiting Kafka.")
          Exit.exit(1)
      }

      server.awaitShutdown()
    }
    catch {
      case e: Throwable =>
        fatal("Exiting Kafka due to fatal exception", e)
        Exit.exit(1)
    }
    Exit.exit(0)
  }
  //生成server
  private def buildServer(props: Properties): Server = {
    val config = KafkaConfig.fromProps(props, false)
    if (config.requiresZookeeper) { //是否在properties中有process.roles=broker,controller配置
    //没有则构造KafkaServer
      new KafkaServer( 
        config,
        Time.SYSTEM,
        threadNamePrefix = None,
        enableForwarding = false
      )
    } else {
    //存在则构造KafkaRaftServer
      new KafkaRaftServer(
        config,
        Time.SYSTEM,
        threadNamePrefix = None
      )
    }
  }

其中config.requiresZookeeper 就是判断/config/kraft/server.properties 中是否有下面的配置
参考Kafka2.8无Zookeeper模式下集群部署


# The role of this server. Setting this puts us in KRaft mode
process.roles=broker,controller
 
# The node id associated with this instance's roles
node.id=1
 
# The connect string for the controller quorum
controller.quorum.voters=1@master:9093,2@slave1:9093,3@slave2:9093

1、server.properties中有process.roles配置

kafka 2.8 如何选择启用kraft还是ZooKeeper(选择逻辑源码,不涉及到kraft的实现)_第1张图片

class KafkaRaftServer(
  config: KafkaConfig,
  time: Time,
  threadNamePrefix: Option[String]
) extends Server with Logging {

  KafkaMetricsReporter.startReporters(VerifiableProperties(config.originals))
  KafkaYammerMetrics.INSTANCE.configure(config.originals)

  private val (metaProps, offlineDirs) = KafkaRaftServer.initializeLogDirs(config)

  private val metrics = Server.initializeMetrics(
    config,
    time,
    metaProps.clusterId
  )

  private val controllerQuorumVotersFuture = CompletableFuture.completedFuture(
    RaftConfig.parseVoterConnections(config.quorumVoters))

  private val raftManager = new KafkaRaftManager[ApiMessageAndVersion](
    metaProps,
    config,
    new MetadataRecordSerde,
    KafkaRaftServer.MetadataPartition,
    KafkaRaftServer.MetadataTopicId,
    time,
    metrics,
    threadNamePrefix,
    controllerQuorumVotersFuture
  )
//这里需要注意,new BrokerServer
  private val broker: Option[BrokerServer] = if (config.processRoles.contains(BrokerRole)) {
    Some(new BrokerServer(
      config,
      metaProps,
      raftManager,
      time,
      metrics,
      threadNamePrefix,
      offlineDirs,
      controllerQuorumVotersFuture,
      Server.SUPPORTED_FEATURES
    ))
  } else {
    None
  }

  private val controller: Option[ControllerServer] = if (config.processRoles.contains(ControllerRole)) {
    Some(new ControllerServer(
      metaProps,
      config,
      raftManager,
      time,
      metrics,
      threadNamePrefix,
      controllerQuorumVotersFuture
    ))
  } else {
    None
  }
//这个是实际的执行,上面的server.startup就是执行的这个
  override def startup(): Unit = {
    Mx4jLoader.maybeLoad()
    //初始化raftManager
    raftManager.startup()
    //执行ControllerServer,这里面有raft的管理,这里不做细致的写
    controller.foreach(_.startup())
    //broker实际上是BrokerServer.startup,可以看一下 private val broker这个方法
    broker.foreach(_.startup())
    AppInfoParser.registerAppInfo(Server.MetricsPrefix, config.brokerId.toString, metrics, time.milliseconds())
    info(KafkaBroker.STARTED_MESSAGE)
  }
//关机
  override def shutdown(): Unit = {
    broker.foreach(_.shutdown())
    raftManager.shutdown()
    controller.foreach(_.shutdown())
    CoreUtils.swallow(AppInfoParser.unregisterAppInfo(Server.MetricsPrefix, config.brokerId.toString, metrics), this)

  }
//等待关机
  override def awaitShutdown(): Unit = {
    broker.foreach(_.awaitShutdown())
    controller.foreach(_.awaitShutdown())
  }

}

之后就执行了BrokerServer.scala中的startup方法
kafka 2.8 如何选择启用kraft还是ZooKeeper(选择逻辑源码,不涉及到kraft的实现)_第2张图片

2、server.properties没有process.roles配置

则会执行KakfaServer.scala中的startup方法,相当于选择用ZooKeeper
kafka 2.8 如何选择启用kraft还是ZooKeeper(选择逻辑源码,不涉及到kraft的实现)_第3张图片

你可能感兴趣的:(#,kafka,kafka,zookeeper,scala)