0. 关键概念
关键概念
Concepts | Function |
---|---|
Topic | 用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上。 |
Partition | 是Kafka中横向扩展和一切并行化的基础,每个Topic都至少被切分为1个Partition。 |
Offset | 消息在Partition中的编号,编号顺序不跨Partition(在Partition内有序)。 |
Consumer | 用于从Broker中取出/消费Message。 |
Producer | 用于往Broker中发送/生产Message。 |
Replication | Kafka支持以Partition为单位对Message进行冗余备份,每个Partition都可以配置至少1个Replication(当仅1个Replication时即仅该Partition本身)。 |
Leader | 每个Replication集合中的Partition都会选出一个唯一的Leader,所有的读写请求都由Leader处理。其他Replicas从Leader处把数据更新同步到本地。 |
Broker | Kafka中使用Broker来接受Producer和Consumer的请求,并把Message持久化到本地磁盘。每个Cluster当中会选举出一个Broker来担任Controller,负责处理Partition的Leader选举,协调Partition迁移等工作。 |
ISR | In-Sync Replica,是Replicas的一个子集,表示目前Alive且与Leader能够“Catch-up”的Replicas集合。由于读写都是首先落到Leader上,所以一般来说通过同步机制从Leader上拉取数据的Replica都会和Leader有一些延迟(包括了延迟时间和延迟条数两个维度),任意一个超过阈值都会把该Replica踢出ISR。每个Leader Partition都有它自己独立的ISR。 |
1. 分析kafka源码的目的
深入掌握kafka的内部原理
深入掌握scala运用
2. server的启动
如下所示(本来准备用时序图的,但感觉时序图没有思维图更能反映,故采用了思维图):
2.1 启动入口Kafka.scala
从上面的思维导图,可以看到Kafka的启动入口是Kafka.scala的main()函数:
def main(args: Array[String]): Unit = { try { val serverProps = getPropsFromArgs(args) val kafkaServerStartable = KafkaServerStartable.fromProps(serverProps) // 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(1) } System.exit(0) }
上面代码主要包含:
从配置文件读取kafka服务器启动参数的getPropsFromArgs()方法;
创建KafkaServerStartable对象;
KafkaServerStartable对象在增加shutdown句柄函数;
启动KafkaServerStartable的starup()方法;
启动KafkaServerStartable的awaitShutdown()方法;
2.2 KafkaServer的包装类KafkaServerStartable
private val server = new KafkaServer(serverConfig) def startup() { try { server.startup() } catch { case e: Throwable => fatal("Fatal error during KafkaServerStartable startup. Prepare to shutdown", e) // KafkaServer already calls shutdown() internally, so this is purely for logging & the exit code System.exit(1) } }
2.3 具体启动类KafkaServer
KafkaServer启动的代码层次比较清晰,加上注释,看懂基本没有问题:
/** * Start up API for bringing up a single instance of the Kafka server. * Instantiates the LogManager, the SocketServer and the request handlers - KafkaRequestHandlers */ def startup() { try { info("starting") if(isShuttingDown.get) throw new IllegalStateException("Kafka server is still shutting down, cannot re-start!") if(startupComplete.get) return val canStartup = isStartingUp.compareAndSet(false, true) if (canStartup) { metrics = new Metrics(metricConfig, reporters, kafkaMetricsTime, true) brokerState.newState(Starting) /* start scheduler */ kafkaScheduler.startup() /* setup zookeeper */ zkUtils = initZk() /* start log manager */ logManager = createLogManager(zkUtils.zkClient, brokerState) logManager.startup() /* generate brokerId */ config.brokerId = getBrokerId this.logIdent = "[Kafka Server " + config.brokerId + "], " socketServer = new SocketServer(config, metrics, kafkaMetricsTime) socketServer.startup() /* start replica manager */ replicaManager = new ReplicaManager(config, metrics, time, kafkaMetricsTime, zkUtils, kafkaScheduler, logManager, isShuttingDown) replicaManager.startup() /* start kafka controller