Kafka能抗住百万并发的秘密...

本文深入探讨了Kafka如何处理百万并发请求,从最初的顺序处理模式到多线程异步处理,再到Reactor模式。Kafka通过Java NIO和Reactor设计模式实现高性能网络架构,包括Acceptor和Processor线程的分工。通过多路复用和线程池,Kafka能够高效处理并发请求,避免阻塞和资源浪费。最后,文章还讨论了Kafka Broker的系统调优策略,如合理设置网络线程和I/O线程数量,以提高吞吐量和降低延迟。
摘要由CSDN通过智能技术生成

这篇文章干货很多,希望你可以耐心读完。

01 总体概述

要想理解 Kafka Broker 请求处理架构设计,我们需要从简单请求处理模型来说起。

对于日常系统开发,我们都知道是基于 Request/Response 的模式来实现的, 对于 Kafka 来说, 无论是 Producer 端、Consumer 端 还是 Broker 端,他们之间的请求交互也都是基于「 Request/Response 」模式来完成的。比如,客户端会通过网络发送消息生产请求给 Broker,而 Broker 处理完成后,会发送对应的响应给到客户端。

下面,我会从自我设计角度出发,如果是我们会如何设计,带你一步步演化出来「 kafka Broker 的网络请求处理 」架构。

在这个过程中,你会看到 Kafka 在处理请求的过程中会遇到哪些高性能和高并发问题,以及架构为什么要这样演进,从而理解 Kafka 这么设计的意义和精妙之处。

02 顺序处理模式

我们从最简单的网络编程思路处理方式讲起。

因为对于 Kafka Broker 来说就是用来接收生产者发送过来的请求,那这个时候最简单的实现大概是这样的:

如上述代码所示:我们可以理解 Kafka 每个服务器启动起来后就是一个 while 循环, 不断的 accept 生产者提交上来的请求, 然后进行处理并存储到磁盘上,这种方式实现最简单,也非常好理解,但是这种方式存在2个致命的缺陷?

  1. 请求阻塞:只能顺序处理每个请求,即每个请求都必须等待前一个请求处理完毕才能得到处理。

  2. 吞吐量非常差:由于只能顺序处理,无法并发,效率太低,所以吞吐量非常差,只适合请求发送非常不频繁的系统。

从上面来看很明显,如果你的 Kafka 系统请求并发量很大,意味着要处理的时间就会越久。那按照前面我们提到的 Kafka「 吞吐量 」的标准,这个方案远远无法满足我们对高性能、高并发的要求。

那有什么更好的方案可以快速处理请求吗?

接下来我们可以试着采取这个方案: 独立线程异步处理模式 。

03 多线程异步处理模式

既然同步方式会阻塞请求,吞吐量差, 我们可以尝试着使用独立线程异步方式进行处理, 即经典的 connection per thread 模型, 那这个时候的实现大概是这样的:

如上述代码所示:同上还是一个 while 循环不断的 accept 生产者提交上来的请求,但是这时候 Kafka 系统会为每个请求都创建一个「 单独的线程 」来处理。

这个实现方案的好处就是:

  1. 吞吐量稍强:相对上面同步方式的方案,一定程度上极大地提高了服务器的吞吐量。

  2. 非阻塞:它是完全异步的,每个请求的处理都不会阻塞下一个请求。

但同样缺陷也同样很明显: 即为每个请求都创建线程的做法开销很大 ,在某些高并发场景下会压垮整个服务。可见,这个方案也只适用于请求发送频率很低的业务场景。还是无法满足我们对高性能、高并发的要求。

既然这种方案还是不能满足, 那么我们究竟该使用什么方案来支撑高并发呢?

这个时候我们可以想想我们日常开发用到的7层负载Nginx或者Redis在处理高并发请求的时候是使用什么方案呢?

从上面启发你可以看出,提升系统 I/O 并发性能的关键思路就是:「 事件驱动 」。

想必大家已经猜到了,没错,就是「 多路复用 」。那么Kafka 是不是也是采用这种方案来实现呢?

这里我们先考虑采用基于「 事件驱动 」的设计方案,当有事件触发时,才会调用处理器进行数据处理。

04 Reactor 模式

在高性能网络编程领域,有一个非常著名的模式——Reactor模式。那么何为「 Reactor模式 」,首先它是基于事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handler;这个Service Handler会同步的将输入的请求轮询地分发给相应的Request Handler进行处理。

借助于 Doug Lea(就是那位让人无限景仰的大爷)的 "Scalable IO in Java" 中讲述的Reactor模式。

"Scalable IO in Java" 的地址是:

http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf

简单来说, Reactor 模式特别适合应用于处理多个客户端并发向服务器端发送请求的场景 。这里借用大神 PDF 中的一幅图来说明 Reactor 架构:

从上面这张图中,我们可以看出多个客户端会发送请求给到 Reactor。Reactor 有个请求分发线程 Dispatcher,也就是图中的绿色的 Acceptor,它会将不同的请求下分发到多个工作线程中处理。

在这个架构中,Acceptor 线程只是用来进行请求分发,所以非常轻量级,因此会有很高的吞吐量。而这些工作线程可以根据实际系统负载情况动态调节系统负载能力,从而达到请求处理的平衡性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
kafka是一个分布式的流处理平台,它可以处理和存储大规模的实时数据流。kafka-run-class是kafka提供的一个脚本工具,用于在命令行中执行指定的类。kafka.tools.GetOffsetShell是用于获取指定topic在指定时间点的偏移信息的工具。 具体来说,kafka.tools.GetOffsetShell通过指定topic、时间点和broker列表来获取该topic在指定时间点的偏移。它的用法类似于以下命令: ``` bin/kafka-run-class.sh kafka.tools.GetOffsetShell --topic <topic> --time <timestamp> --broker-list <broker-list> --partitions <partitions> ``` 其中,<topic>是要查询的topic名称,<timestamp>是要查询的时间点,<broker-list>是broker的地址列表,<partitions>是要查询的分区编号。该命令会返回指定topic在指定时间点的偏移信息。 另外,kafka.tools.ConsumerOffsetChecker是kafka提供的另一个工具,用于检查消费者的偏移信息。它可以通过指定zookeeper连接、消费者组和topic来获取消费者的偏移信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [kafka监控命令kafka-run-class.sh查看消费了多少条数据](https://blog.csdn.net/m0_37739193/article/details/73849523)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [kafka_2.9.2-0.8.2.1.tgz](https://download.csdn.net/download/shy_snow/9372309)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值