Network Layer(网络层) 是Kafka Broker处理所有请求的入口。Kafka基于Java NIO实现了一套 Reactor线程模型 ,其核心流程就是与客户端建立连接,然后对请求进行解析,封装成Request对象传递给API层,同时接受API层的处理结果,封装后响应给客户端。
本章,我将先对网络层的整体架构进行分析,然后对其中的一个核心组件—— Acceptor线程 进行讲解。
一、整体架构
我们来看下网络层的整体架构:
整个网路层,包含的核心组件和功能说明如下:
SocketServer # 网络层的整体封装类
|-- Acceptor # Acceptor线程,负责监听并建立与客户端的连接
|-- Processor # Processor线程,负责监听读写事件,并解析请求/响应
Selector # 对Java NIO中的Selector进行了封装
KafkaChannel # 对Java NIO中的SocketChannel进行了封装
TransportLayer # 对KafkaChannel屏蔽底层的字节读写
RequestChannel # 请求队列,是与API层进行通信交互的通道
|-- Request # 传递给API层的请求Request对象
|-- Response # 接受API层返回的Response对象
1.1 处理流程
我先根据上图,讲解下网络层处理请求的大概流程,便于大家有个印象,后续再对每个组件的源码进行分析:
-
首先,每个Broker启动后,会根据
server.properties
中的参数配置创建三类核心线程:Acceptor线程: 通过
listeners
配置,每一组IP/端口都会创建一个Endpoint对象和Acceptor线程,并建立映射,EndPoint是对端口IP的抽象;Processor线程: 通过
num.network.threads
配置,默认3个,即一个Acceptor线程对应3个Processor线程;RequestHandler线程: 通过
num.io.threads
配置,默认8个,被封装在一个 KafkaRequestHandlerPool线程池 中。 -
Acceptor线程启动后,默认监听Broker的本机地址和9092端口,底层基于Java NIO监听Socket的连接事件
OP_ACCEPT
; -
接着,当客户端请求建立连接时,Acceptor会监听到该事件,然后完成连接的建立,并把建立好连接的SocketChannel通过Round Robin轮询的方式分配给各个Processor线程;
-
每个Processor线程会把接受到的SocketChannel,缓存到自己内部的一个队列(ConcurrentLinkedQueue)中;
-
当SocketChannel监听读事件
OP_READ
发生时,每个Processor会通过底层的NIO组件读取请求字节,封装成Request对象,扔到一个名为 RequestChannel 的组件中; -
RequestChannel内部有一个缓存Request请求的全局队列(ArrayBlockingQueue),默认最多可以缓存500个请求,可通过参数
queued.max