启动入口类:kafka.Kafka
这个类中只有两个方法,getPropsFromArgs 和 main方法
前者根据配置文件以及默认配置,返回一个Properties对象,main方法是启动方法;
main方法重点代码是下面这句:
kafkaServerStartable.startup()
kafkaServerStartable类
这个类的主要作用是将kafkaServer以及KafkaConfig统一起来;
两个关键字段:staticServerConfig 以及 server;
前者的类型是KafkaConfig类型,后者是KafkaServer类型;KafkaConfig类中包含了将Properties对象转为KafkaConfig对象的方法,并且定义了相关属性的默认值,想了解kafka都有哪些配置,可以查看这个类:
KafkaConfig.fromProps(serverProps, false) //serverProps 就是上面提到的properties对象
server字段是kafka的核心,我们经常说的broker实际上就是一个KafkaServer对象;
在kafkaServerStartable.startup()方法中,只有一行关键代码,具体如图所示:
kafkaServer类
我们经常说的broker,实际上就是一个kafkaServer对象;下面针对其startup方法进行解读:
状态校验
首先是状态校验,判断kafkaServer的当前状态是否可以启动,这里采用了CAS方式;
val canStartup = isStartingUp.compareAndSet(false, true)
如果可以启动,那么将broker的状态设置为Staring状态
brokerState.newState(Starting)
初始化zk链接
initZkClient(time)
获取或者创建集群ID,这里会先尝试在zk上获取集群id,如果获取不到,说明当前集群不存在,则创建集群ID;
_clusterId = getOrGenerateClusterId(zkClient)
从本地配置文件中加载配置信息,比如当一个broker失败重启时,会在本地目录中保留一些meta信息,这里的:getBrokerMetadataAndOfflineDirs是一个方法调用,Scala的特有语法;
val (preloadedBrokerMetadataCheckpoint, initialOfflineDirs) = getBrokerMetadataAndOfflineDirs
进一步校验本地的clusterId和zk上的clsuterId是否相同,如果不相同则会启动失败;
初始化brokerId,如果配置文件中有brokerId,则按照配置文件指定的id,否则根据zk上的配置信息生成id;
config.brokerId = getOrGenerateBrokerId(preloadedBrokerMetadataCheckpoint)
动态绑定config,完成本地配置与zk配置信息的同步;
config.dynamicConfig.initialize(zkClient)
后面会启动一个线程池来执行一些定时后台任务:
kafkaScheduler = new KafkaScheduler(config.backgroundThreads)kafkaScheduler.startup()
创建Server的监控指标:
/* create and configure metrics */val reporters = new util.ArrayList[MetricsReporter]reporters.add(new JmxReporter(jmxPrefix))val metricConfig = KafkaServer.metricConfig(config)metrics = new Metrics(metricConfig, reporters, time, true)/* register broker metrics */_brokerTopicStats = new BrokerTopicStats
启动日志管理组件:
/* start log manager */logManager = LogManager(config, initialOfflineDirs, zkClient, brokerState, kafkaScheduler, time, brokerTopicStats, logDirFailureChannel)logManager.startup()
启动SocketServer,注册相关的监听事件;
// Create and start the socket server acceptor threads so that the bound port is known.// Delay starting processors until the end of the initialization sequence to ensure// that credentials have been loaded before processing authentications.socketServer = new SocketServer(config, metrics, time, credentialProvider)socketServer.startup(startupProcessors = false)
启动副本管理组件:
/* start replica manager */replicaManager = createReplicaManager(isShuttingDown)replicaManager.startup()
broker信息同步到zk,并进行一些检查等:
val brokerInfo = createBrokerInfoval brokerEpoch = zkClient.registerBroker(brokerInfo)// Now that the broker is successfully registered, checkpoint its metadatacheckpointBrokerMetadata(BrokerMetadata(config.brokerId, Some(clusterId)))
到此位置broker启动流程完成;
后面还有一些集群相关的初始化操作,比如token管理,集群选主相关的线程启动,事务协调器等等;