Kafka集群是由若干个broker组成的,启动kafka集群就是将集群中的broker启动并正常运行。broker与broker之间、broker与生成者之间、broker与消费者之间都存在各种交互。下面简单介绍一下broker的启动流程。
启动broker的脚本:
nohup ./bin/kafka-server-start.sh config/server.properties &
其中,脚本文件kafka-server-start.sh启动的操作如下:
exec $base_dir/kafka-run-class.sh $EXTRA_ARGS kafka.Kafka "$@"
最终执行的是kafka.Kafka这个类,kafka.Kafka的代码如下:
object Kafka extends Logging {
def main(args: Array[String]): Unit = {
......
try {
val props = Utils.loadProps(args(0))
val serverConfig = new KafkaConfig(props)
KafkaMetricsReporter.startReporters(serverConfig.props)
val kafkaServerStartable = new KafkaServerStartable(serverConfig)
// attach shutdown handler to catch control-c
Runtime.getRuntime().addShutdownHook(new Thread() {
override def run() = {
kafkaServerStartable.shutdown
}
})
kafkaServerStartable.startup
kafkaServerStartable.awaitShutdown
}
catch {
case e: Throwable => fatal(e)
}
System.exit(0)
}
}
通过上面的代码可以看出,代码通过执行kafkaServerStartable.startup来启动系统。KafkaServerStartable的启动代码如下:
class KafkaServerStartable(val serverConfig: KafkaConfig) extends Logging {
private val server = new KafkaServer(serverConfig)
def startup() {
try {
server.startup()
AppInfo.registerInfo()
}
catch {
......
}
}
......
}
从上面的代码可以看出,KafkaServerStartable的启动函数主要是封装了KafkaServer的启动函数startup()。下面我们就一起来看一下KafkaServer的代码结构。
class KafkaServer(val config: KafkaConfig, time: Time = SystemTime) extends Logging with KafkaMetricsGroup {
this.logIdent = "[Kafka Server " + config.brokerId + "], "
private var isShuttingDown = new AtomicBoolean(false)
private var shutdownLatch = new CountDownLatch(1)
private var startupComplete = new AtomicBoolean(false)
val brokerState: BrokerState = new BrokerState
val correlationId: AtomicInteger = new AtomicInteger(0)
var socketServer: SocketServer = null
var requestHandlerPool: KafkaRequestHandlerPool = null
var logManager: LogManager = null
var offsetManager: OffsetManager = null
var kafkaHealthcheck: KafkaHealthcheck = null
var topicConfigManager: TopicConfigManager = null
var replicaManager: ReplicaManager = null
var apis: KafkaApis = null
var kafkaController: KafkaController = null
val kafkaScheduler = new KafkaScheduler(config.backgroundThreads)
var zkClient: ZkClient = null
......
}
KafkaServer的类中包含了系统运行需要的各个模块,下面介绍一下主要模块的功能。
1、SocketServer:broker的通信模块。用来和其它broker、生成者、消费者发送、接收消息。 首先会创建一个Acceptor线程监听默认端口9092的socket请求,当有新的连接加入时会创建一个对应的SocketChannel以轮询的方式转发给Processor线程中的某一个,并由其处理该SocketChannel接下来的请求,会将请求放置在RequestChannel的请求队列中。当Processor监听到SocketChannel请求的响应时,会将响应请求从RequestChannel的相应队列中取出来发送给客户端。
2、KafkaRequestHandlerPool:处理socket请求的线程池。会将socket请求从队列中取出来然后调用KafkaApis完成业务逻辑的处理,并将处理的结果放回到RequestChannel的响应队列。
3、LogManager:Kafka的日志管理模块。主要是删除过期数据和冗余数据、刷新脏数据,对日志文件进行Checkpoint和日志合并
4、ReplicationManager:Kafka的副本管理模块。主要是针对Topic的分区副本数据进行管理,包括副本leader和ISR状态的变化、副本的删除等。
5、OffsetManager:Kafka的偏移量offset的管理模块。主要是偏移量offset的保存和读取。
6、KafkaScheduler:Kafka的后台任务调度资源池。为LogManager、ReplicationManager、OffsetManager等模块提供线程调度服务。
7、KafkaApis:kafka的业务逻辑实现层。根据不同的Request处理不同的请求。处理去请求包括ProduceKey、FetchKey、OffsetsKey、MetadataKey、LeaderAndIsrKey、StopReplicaKey、UpdateMetadataKey、ControlledShutdownKey、OffsetCommitKey、OffsetFetchKey、ConsumerMetadataKey。
8、KafkaHealthCheck:broker的健康检查模块。broker在zookeeper上注册目录为/brokers/ids,当broker在线时,对应的id存在,否则不存在。
9、TopicConfigManager:topic的配置管理模块。在zookeeper上注册目录/config/changes,当数据发送变化时通过回调函数来感知topic的变化。
10、KafkaController:kafka的集群控制管理模块。由于zookeeper保存了集群中的kafka集群的元数据,KafkaController通过注册不同的回调函数来监听不同元数据的变化,当这些元数据发生变化时,KafkaController就可以感知到这些变化并作出不同的响应,从而达到管理集群的目的。