从kafka的请求处理模型理解Reactor模式

本文深入探讨了Kafka请求处理的全过程,解析了Reactor模式如何优化请求处理效率,介绍了Broker端的网络线程池与IO线程池分工合作机制,以及Purgatory组件在处理延迟请求中的作用。

内容总结于课程: kafka请求是怎么被处理的

扩展阅读: Scalable IO in Java

简介

Kafka 自己定义了一组请求协议,用于实现各种各样的交互操作。比如常见的 PRODUCE 请求是用于生产消息的,FETCH 请求是用于消费消息的,METADATA 请求是用于请求 Kafka 集群元数据信息的。所有的请求都是通过 TCP 网络以 Socket 的方式进行通讯的

今天主要整理一下kafka Broker 端处理请求的全流程

关于处理请求,很容易想到的两个方案:

1、单线程处理请求: 由于单线程,吞吐量极差,
2、线程池处理请求: 确实优化了很多,但是每一个线程的粒度太大,处理了连接、处理、返回等操作。
3、Reactor模式: Reactor 模式是事件驱动架构的一种实现方式,特别适合应用于处理多个客户端并发向服务器端发送请求的场景。
在这里插入图片描述
client: 客户端,多个客户端会发送请求给到 Reactor
dispatch(acceptor): Reactor 有个请求分发线程 Dispatcher,也就是图中的 Acceptor,它会将不同的请求下发到多个工作线程中处理。Acceptor 线程只是用于请求分发,不涉及具体的逻辑处理,非常得轻量级,因此有很高的吞吐量表现。而这些工作线程可以根据实际业务处理需要任意增减,从而动态调节系统负载能力。

对比到kafka中的模型图:

在这里插入图片描述
Broker端有ScoketServer组件,类似于 Reactor 模式中的 Dispatcher,也有对应的 Acceptor 线程和一个工作线程池,只不过在 Kafka 中,这个工作线程池有个专属的名字,叫网络线程池。Kafka 提供了 Broker 端参数 num.network.threads,用于调整该网络线程池的线程数。其默认值是 3,表示每台 Broker 启动时会创建 3 个网络线程,专门处理客户端发送的请求。

Acceptor线程采用轮询方式将请求公平分发到所有网络线程,防止请求处理的倾斜。

网络线程池处理请求

在这里插入图片描述
网络线程将进来的请求放入到一个共享请求队列中。Broker 端还有个 IO 线程池,负责从该队列中取出请求,执行真正的处理。如果是 PRODUCE 生产消息请求,则将消息写入到底层的磁盘日志中;如果是 FETCH 请求,则从磁盘或页缓存中读取消息。

IO线程处理的才是真正处理的逻辑。Broker通过参数num.io.threads加粗样式控制了这个线程池中的线程数。目前该参数默认值是 8,表示每台 Broker 启动后自动创建 8 个 IO 线程处理请求。

Purgatory组件: 用来缓存延迟请求,一些未满足条件不能立即执行的请求。比如设置acks=all的produce请求,需要等待收到ISR中所有的副本都持久化消息后才将请求返回,此时处理该请求的IO线程必须等待其他Broker的写入。

kafka请求分类
  • PRODUCE 和 FETCH 这类请求称为数据类请求
  • 负责更新 Leader 副本、Follower 副本以及 ISR 集合的 LeaderAndIsr 请求,负责勒令副本下线的 StopReplica 请求等为控制类请求
思考,不同类型的请求,是否需要分开处理呢?
问题:

假设我们有个主题只有 1 个分区,该分区配置了两个副本,其中 Leader 副本保存在 Broker 0 上,Follower 副本保存在 Broker 1 上。假设 Broker 0 这台机器积压了很多的 PRODUCE 请求,此时你如果使用 Kafka 命令强制将该主题分区的 Leader、Follower 角色互换,那么 Kafka 内部的控制器组件(Controller)会发送 LeaderAndIsr 请求给 Broker 0,显式地告诉它,当前它不再是 Leader,而是 Follower 了,而 Broker 1 上的 Follower 副本因为被选为新的 Leader,因此停止向 Broker 0 拉取消息。
这时,一个尴尬的场面就出现了:如果刚才积压的 PRODUCE 请求都设置了 acks=all,那么这些在 LeaderAndIsr 发送之前的请求就都无法正常完成了。就像前面说的,它们会被暂存在 Purgatory 中不断重试,直到最终请求超时返回给客户端。

个人解决:

Broker中实现一个有限队列,将控制类的请求赋予更高的优先级。存在的问题,一旦优先队列满了之后,无法处理新的控制类请求。

社区解决方案:

完全拷贝网络处理架构,将两类请求进行分离,scoket使用的不同端口,使用起来需要提供不同的listeners配置,指定哪个端口处理哪一类的请求

### ### Reactor 模式的基本概念 Reactor 模式是一种基于事件驱动的并发编程模型,主要用于处理多个客户端请求。它通过将事件处理逻辑与事件分发机制解耦,实现了高性能、可扩展的并发处理能力[^4]。该模式的核心在于一个事件循环(Event Loop),它负责监听和分发各种 I/O 事件,如网络连接、数据读写等。 在 Reactor 模式中,通常包含以下几个关键组件: - **Reactor**:负责监听并分发事件到相应的处理器。 - **Handler**:处理具体的 I/O 事件,如接收连接、读取数据或写入数据。 - **Acceptor**:专门用于处理新连接的建立。 - **Connector**:用于主动发起连接。 这种设计使得系统能够高效地管理大量并发连接,同时避免了传统多线程模型中的线程切换和锁竞争问题。 ### ### Reactor 模式的工作原理 Reactor 模式的工作流程可以分为以下几个步骤: 1. **注册事件**:应用程序向 Reactor 注册感兴趣的事件,例如套接字上的读就绪或写就绪。 2. **事件等待**:Reactor 进入事件循环,等待事件的发生。 3. **事件分发**:当某个事件发生时,Reactor 将其分发给预先绑定的 Handler 处理。 4. **事件处理**:Handler 执行相应的业务逻辑,可能涉及进一步的数据读取或写入操作。 为了提高性能,Reactor 模式通常结合非阻塞 I/O 和多路复用技术(如 Linux 的 `epoll` 或 Windows 的 IOCP)来实现高效的事件检测和处理[^2]。 以下是一个简单的伪代码示例,展示了如何使用 Reactor 模式进行事件处理: ```python class EventHandler: def handle_read(self, fd): data = read(fd) process_data(data) def handle_write(self, fd): write(fd, response) class Reactor: def __init__(self): self.handlers = {} def register_handler(self, fd, handler): self.handlers[fd] = handler def run(self): while True: events = wait_for_events() # 使用 epoll 或 select 等机制 for fd, event in events: if event == 'read': self.handlers[fd].handle_read(fd) elif event == 'write': self.handlers[fd].handle_write(fd) # 创建 Reactor 实例并注册处理reactor = Reactor() handler = EventHandler() reactor.register_handler(socket_fd, handler) reactor.run() ``` 上述代码展示了 Reactor 的基本结构和事件处理流程,实际应用中会更加复杂,并且通常由框架(如 Twisted)提供更高级别的抽象。 ### ### Reactor 模式的应用场景 Reactor 模式因其高效性和可扩展性,在多种高性能网络服务中有广泛应用,包括但不限于: - **Web 服务器**:如 Nginx 和 Node.js,利用 Reactor 模式处理大量的 HTTP 请求。 - **游戏服务器**:实时游戏中需要维持成千上万的连接,Reactor 模式能够有效管理这些连接并快速响应玩家操作。 - **分布式系统通信层**:在微服务架构中,服务间的通信往往需要异步、非阻塞的支持,Reactor 模式提供了良好的基础。 - **消息中间件**:如 Kafka 和 RabbitMQ,在底层网络通信中采用了类似的事件驱动机制以提升吞吐量。 此外,随着云原生时代的到来,结合协程等新技术,事件驱动架构正在不断进化。理解 Reactor 模式的核心思想,将帮助开发者构建更高效、更可靠的网络应用系统[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值