Kafka服务端源码之网络
网络传输关键类及流程图:
上图可以看出有如下几个关键线程和关键类:
- Acceptor线程:接受并配置新连接的线程。 每个端点中有一个。
- **Processor线程:**处理来自单个连接的所有请求的线程。 其中有N个并行运行,每个都有自己的选择器
- **RequestChannel类:**处理请求,并将请求缓存在该类的requestQueue中,发送响应等功能
- KafkaRequestHandlerPool类: 线程处理池,有多个handler处理消息
- **KafkaRequestHandler类:**真正处理消息的类
Kafka网络之初始化
kafka启动过程主要是各个线程的准备工作,包括Accecptor线程启动成功并监听所有连接该服务器的生产者。
各个Processor启动轮询SocketChannel的消息;
RequestHandlerPool初始化,并开启各个RequestHanler轮询RequestChannel中的RequestQueue中是否有消息可以消费
启动Acceptor和Processor的入口类为SocketServer,启动的方法是startup():这里粘贴主要代码
/**
* 启动套接字服务器。 启动所有侦听器的接受器。
* 如果startupProcessors为true,则启动处理器。 如果不是,则仅在调用kafka.network.SocketServer.startDataPlaneProcessors()
* 或kafka.network.SocketServer.startControlPlaneProcessor()时启动处理器。
* 处理器的延迟启动用于延迟对客户端连接的处理,直到服务器完全初始化为止,
* 例如,以确保在执行身份验证之前已加载所有凭据。
* 接收器始终在启动过程中启动,因此即使使用临时端口,此方法完成后,绑定端口也将是已知的。
* 当处理器启动并调用org.apache.kafka.common.network.Selector.poll时,将处理此服务器上的传入连接。
*/
def startup(startupProcessors: Boolean = true): Unit = {
this.synchronized {
//连接的一些配额信息
connectionQuotas = new ConnectionQuotas(config, time)
/**创建控制Acceptor以及Processor
-control-plane :
- 处理来自控制器的请求。 这是可选的,可以通过指定“ control.plane.listener.name”进行配置。 如果未配置,则控制器请求由数据平面处理。
- 线程模型是处理新连接的1个Acceptor线程。Acceptor具有1个处理器线程,该线程具有自己的选择器并从套接字读取请求。 1处理程序线程,用于处理请求并向处理器线程返回响应以进行写入。
*/
createControlPlaneAcceptorAndProcessor(config.controlPlaneListener)
/**
-data-plane:
- 处理来自客户端和集群中其他代理的请求。
- 线程模型是每个侦听器1个Acceptor线程,用于处理新连接。 通过在KafkaConfig中为“侦听器”指定多个“,”分隔的端点,可以配置多个数据平面。 接受者有N个处理器线程,每个线程都有自己的选择器并从套接字读取请求。M个处理程序线程处理请求并向处理器线程返回响应以进行写入。
*/
//Acceptor会在该方法中启动
createDataPlaneAcceptorsAndProcessors(config.numNetworkThreads, config.dataPlaneListeners)
if (startupProcessors) {
//启动Processor
startControlPlaneProcessor(Map.empty)
startDataPlaneProcessors(Map.empty)
}
}
}
//createDataPlaneAcceptorsAndProcessors(config.numNetworkThreads,config.dataPlaneListeners)
private def createDataPlaneAcceptorsAndProcessors(dataProcessorsPerListener: Int,
endpoints: Seq[EndPoint]): Unit = synchronized {
endpoints.foreach {
endpoint =>
connectionQuotas.addListener(config, endpoint.listenerName)
//创建Acceptor
val dataPlaneAcceptor = createAcceptor(endpoint, DataPlaneMetricPrefix)\
//向Acceptor中添加Processor
addDataPlaneProcessors(dataPlaneAcceptor, endpoint, dataProcessorsPerListener)
//启动Acceptor线程
KafkaThread.nonDaemon(s"data-plane-kafka-socket-acceptor-${endpoint.listenerName}-${endpoint.securityProtocol}-${endpoint.port}", dataPlaneAcceptor).start()
dataPlaneAcceptor.awaitStartup()
dataPlaneAcceptors.put(endpoint, dataPlaneAcceptor)
info(s"Created data-plane acceptor and processors for endpoint : $endpoint")
}
}
//addDataPlaneProcessors
private def addDataPlaneProcessors(acceptor: Acceptor, endpoint: EndPoint, newProcessorsPerListener: Int): Unit = synchronized {
val listenerName: ListenerName = endpoint.listenerName
val securityProtocol: SecurityProtocol = endpoint.securityProtocol
val listenerProcessors = new ArrayBuffer[Processor]()
for (_ <- 0 until newProcessorsPerListener) {
//创建Processor线程
val processor