1 Apache Kafka 自己定义了组请求协议,用于实现各种交互操作。常见有:
a. PRODUCE 请求用于生产消息
b. FETCH请求是用于消费消息
c. METADATA请求是用于请求Kafka集群元数据信息。
Kafka定义了很多类似的请求格式,所有的请求都是通过TCP网络以Socket的方式进行通讯的。
2 KaKfa Broker端处理请求的全流程
A :常用请求处理方案
a:顺序处理请求
实现方法简答,但吞吐量太差是致命缺陷。因为是顺序处理,每个请求都必须等待前一个请求处理完毕才能得到处理。这只适用于请求发送非常不频繁的系统。
b:每个请求使用单独线程处理
它是完全异步的,每个请求的处理都创建单独线程处理,但缺陷明显,为每个请求都创建线程开销极大,某些场景甚至会压垮整个服务。
B :Kafka的方案:使用Reactor模式
a:Reactor模式是JUC包作者的作品
b:Reactor模式是事件驱动架构的一种实现方式,特别适应用于处理多个客户端并发向服务端发送请求的场景。
3 Kafka的请求处理方式
A :Reactor模式中,多个客户端发送请求到Reactor。Reactor有个请求分发线程Dispatcher,它会将不同的请求下发到多个工作线程中处理。
Acceptor线程只用于请求分发,不涉及具体逻辑处理,因此有很高的吞吐量。而工作线程可以根据实际业务处理需要任意增减,从而动态调节系统负载能力。
B :kakfa中,Broker端有个SocketServer组件,类似于Reactor模式中的Dispatcher,他也有对应的Acceptor线程和一个工作线程池,在kafka中,被称为网络线程池。
Broker端参数num.network.threads,用于调整该网络线程池的线程数,默认为4,表示每台Broker启动时,会创建3个网络线程,专门处理客户端发送的请求。
C :Acceptor线程采用轮询的方式将入站请求公平的发送到所有网络线程中。
D :当网络线程接收到请求后,Kafka在这个环节又做了一层异步线程池的处理。
(1)当网络线程拿到请求后,她不是自己处理,而是将请求放入到一个共享请求队列中。
(2)Broker端还有个IO线程池,负责从该队列中取出请求,执行真正的处理。如果是PRODUCE生产请求,则将消息写入到底层的磁盘日志中;如果是FETCH请求,则从磁盘或页缓存中读取消息。
E :IO线程池中的线程是执行请求逻辑的线程。Broker端参数num.io.threads控制了这个线程数,默认为8,表示每台Broker启动后自动创建8个IO线程处理请求。
F :请求队列是所有网络线程共享的,而响应队列则是每个网络线程专属的。原因在于Dispatcher只是用于请求分发而不负责响应回传,因此只能让每个网络线程自己发送Repsone给客户端,所有这些Response没必要放在一个公共的地方。
G :Purgatory组件,专门用来缓存延时请求(Delayed Requset)。如设置了acks=all的PRODUCE请求,该请求要必须等待ISR中所有副本都接收了消息后才能返回,此时处理该请求的IO线程就必须瞪大其他Broker的写入结果。当请求不能立即处理时,他就会暂存在Purgatory中。待满足了完成条件,IO线程会继续处理该请求,并将Response放入到对应的网络线程的响应队列中
4 Kafka对请求的处理特点
A :Kafka Broker对所有的请求都是一视同仁的。
B :这些请求根据功能,可分为不同的请求类型。从业务的权重角度来讲,是有高低之分的,如控制类请求可以影响数据类请求。
C :无原则的平等,会造成混乱
社区采取的方案是,同时创建两套完全样的组件,实现两类请求的分离。
展开