浅谈Kafka Broker 请求处理流程

概述

首先,无论是 Kafka 客户端还是 Broker 端,它们之间的交互都是通过请求-响应的方式完成的。Kafka 自己定义了一套请求协议,用于实现各种各样的交互操作,所有的请求都是通过 TCP 以 Socket进行通讯的。比如 PRODUCE 请求是用于生产消息的,FETCH 请求是用于消费消息的,METADATA 请求是用于请求 Kafka 集群元数据信息的。

因为采用顺序请求的方式吞吐量太低,采用每个请求对应一个线程的方式开销太大,所以Kafka采用Reactor设计模式(1 + M + N) → 经典高并发IO设计模式 来处理请求。

在这个架构中,Kafka Broker 端有个 SocketServer 组件,即 Reactor 模式中的 Dispatcher,它有对应的 Acceptor 线程和一个 Worker 线程池 → 叫网络线程池。Kafka 提供了 Broker 端参数 num.network.threads(默认为3),用于调整该网络线程池的线程数。

具体流程

  1. Acceptor 采用轮询的方式将请求公平地发到所有网络线程中,当Kafka网络线程接收到请求后,他并不会顺序处理,Kafka 在这个环节又做了一层异步线程池的处理,将请求放入到一个共享请求队列中。
  2. 之后,由IO线程池负责从该队列中取出请求,执行真正的处理,Broker 端参数 num.io.threads(默认为8→如果CPU资源充足可以适当调大) 控制了这个线程池中的线程数。如果是 PRODUCE 生产请求,则将消息写入到底层的磁盘日志中;如果是 FETCH 请求,则从磁盘或页缓存中读取消息。
  3. 当 IO 线程处理完请求后,会将生成的响应发送到网络线程池的响应队列中,然后由对应的网络线程负责将 Response 返还给客户端。
  4. 如果是延时请求(一时未满足条件不能立刻处理的请求 → 设置acks=all的PRODUCE请求)的话,还需要在进入响应队列之前先进入 Purgatory 炼狱组件中等待,

可以看到,Kafka中的Reactor是经典的1(监听) + M(读写) + N(业务逻辑)的设计模式。

浅谈Kafka Broker 请求处理流程_第1张图片
图引自胡夕老师《Kafka核心技术与实战》极客时间专栏

其中的细节

需要注意一个细节: 请求队列和响应队列的差别
请求队列是所有网络线程共享的,而响应队列则是每个网络线程专属的。
这么设计的原因就在于,Dispatcher 只是用于请求分发而不负责响应回传,因此只能让每个网络线程自己发送 Response 给客户端,所以这些 Response 也就没必要放在一个公共的地方。

参考自胡夕老师《Kafka核心技术与实战》极客时间专栏,老师的课很棒,强烈推荐!

你可能感兴趣的:(Kafka,kafka,java,分布式)