Kafka server by Kafka.scala
the main function main
method starts. KafkaServerStartable
Class provides read configuration files, startup method / stop services. The Start / Stop Service is the final call of KafkaServer
the startup/shutdown
method.
Start Process
- Start zk client.
- Start dynamic configuration.
- Start scheduling thread pool.
- Start Log Manager background threads, including cleaning up the log, the log disk brush, delete the log, log compression.
- Start NIO Socket services .
- Initializing a sink
Acceptor
, i.e. start NIO Socket. - Adding
num.network.threads
receivers to the channel requestRequestChannel
processor cacheConcurrentHashMap
, key number is incremented, value for the processorProcessor
. Acceptor
ExecutionCountDownLatch.await
waits for a notification to start.- Cache
Acceptor
toConcurrentHashMap
, key isEndPoint
, value isAcceptor
.
- Initializing a sink
- Start copy manager.
- Registered broker in zk.
- The controller.
- Startup group coordinator.
- Start transaction coordinator.
- Initialization
KafkaApis
. - The processor cache initialization thread pool .
- Start
num.io.threads
request processor threadsKafkaRequestHandler
. - From blocking queue
ArrayBlockingQueue
acquisition request, callingKafkaApis.handle
the method, for centralized processing request.
- Start
- Start processor thread .
- First
CountDownLatch.countDown
notice wake upAcceptor
threads.- The use of
NIO.select
polling. - If an event can receive ready, then the current
SocketChannel
addition of buffer queueConcurrentLinkedQueue
- The use of
- Taken out from the queue buffer
SocketChannel
, to bindKafkaChannel
. - The received request to the cache limit blocking queue length
ArrayBlockingQueue
- First
Request processing flow
Detailed source code analysis
Acceptor threads
def run() {
serverChannel.register(nioSelector, SelectionKey.OP_ACCEPT) // 注册接收事件
startupComplete() // 通知 Acceptor 线程
var currentProcessor = 0
while (isRunning) {
val ready = nioSelector.select(500) // 轮询事件
if (ready > 0) {
val keys = nioSelector.selectedKeys()
val iter = keys.iterator()
while (iter.hasNext && isRunning) {
val key = iter.next
iter.remove()
if (key.isAcceptable) { // 有可接受事件
val processor = synchronized {
currentProcessor = currentProcessor % processors.size
processors(currentProcessor) // 缓存 Processor
}
accept(key, processor) // 将 SocketChannel 缓存到队列
}
}
}
}
}
Processor thread
override def run() {
startupComplete() // CountDownLatch.countDown 唤醒 Acceptor 线程。
while (isRunning) {
configureNewConnections() // 从缓存队列取出 SocketChannel,绑定到 KafkaChannel
processNewResponses() // 处理返回客户端的响应
poll() // Kafka.Selector 轮询读取/写入事件
processCompletedReceives() // 处理客户端的请求,放到阻塞队列
processCompletedSends() // 处理返回客户端响应后的回调
processDisconnected() // 断开连接后的处理
}
}
KafkaRequestHandler thread blocking queue
def run() {
while (!stopped) {
val startSelectTime = time.nanoseconds
// 从阻塞队列拉取请求
val req = requestChannel.receiveRequest(300)
req match {
case request: RequestChannel.Request =>
try {
apis.handle(request) // 调用`KafkaApis.handle`方法,进行集中处理请求。
}
}
}
}
KSelector
Analysis of client reference source.