Kafka核心技术与实战
胡夕
人人贷计算平台部总监,Apache Kafka Contributor
立即订阅
8408 人已学习
课程目录
已完结 46 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么要学习Kafka?
免费
Kafka入门 (5讲)
01 | 消息引擎系统ABC
02 | 一篇文章带你快速搞定Kafka术语
03 | Kafka只是消息引擎系统吗?
04 | 我应该选择哪种Kafka?
05 | 聊聊Kafka的版本号
Kafka的基本使用 (3讲)
06 | Kafka线上集群部署方案怎么做?
07 | 最最最重要的集群参数配置(上)
08 | 最最最重要的集群参数配置(下)
客户端实践及原理剖析 (14讲)
09 | 生产者消息分区机制原理剖析
10 | 生产者压缩算法面面观
11 | 无消息丢失配置怎么实现?
12 | 客户端都有哪些不常见但是很高级的功能?
13 | Java生产者是如何管理TCP连接的?
14 | 幂等生产者和事务生产者是一回事吗?
15 | 消费者组到底是什么?
16 | 揭开神秘的“位移主题”面纱
17 | 消费者组重平衡能避免吗?
18 | Kafka中位移提交那些事儿
19 | CommitFailedException异常怎么处理?
20 | 多线程开发消费者实例
21 | Java 消费者是如何管理TCP连接的?
22 | 消费者组消费进度监控都怎么实现?
深入Kafka内核 (5讲)
23 | Kafka副本机制详解
24 | 请求是怎么被处理的?
25 | 消费者组重平衡全流程解析
26 | 你一定不能错过的Kafka控制器
27 | 关于高水位和Leader Epoch的讨论
管理与监控 (12讲)
28 | 主题管理知多少?
29 | Kafka动态配置了解下?
30 | 怎么重设消费者组位移?
31 | 常见工具脚本大汇总
32 | KafkaAdminClient:Kafka的运维利器
33 | Kafka认证机制用哪家?
34 | 云环境下的授权该怎么做?
35 | 跨集群备份解决方案MirrorMaker
36 | 你应该怎么监控Kafka?
37 | 主流的Kafka监控框架
38 | 调优Kafka,你做到了吗?
39 | 从0搭建基于Kafka的企业级实时日志流处理平台
高级Kafka应用之流处理 (3讲)
40 | Kafka Streams与其他流处理平台的差异在哪里?
41 | Kafka Streams DSL开发实例
42 | Kafka Streams在金融领域的应用
结束语 (1讲)
结束语 | 以梦为马,莫负韶华!
特别放送 (2讲)
加餐 | 搭建开发环境、阅读源码方法、经典学习资料大揭秘
用户故事 | 黄云:行百里者半九十
Kafka核心技术与实战
登录|注册

24 | 请求是怎么被处理的?

胡夕 2019-07-27
你好,我是胡夕。今天我要和你分享的主题是:Kafka 请求是怎么被处理的。
无论是 Kafka 客户端还是 Broker 端,它们之间的交互都是通过“请求 / 响应”的方式完成的。比如,客户端会通过网络发送消息生产请求给 Broker,而 Broker 处理完成后,会发送对应的响应给到客户端。
Apache Kafka 自己定义了一组请求协议,用于实现各种各样的交互操作。比如常见的 PRODUCE 请求是用于生产消息的,FETCH 请求是用于消费消息的,METADATA 请求是用于请求 Kafka 集群元数据信息的。
总之,Kafka 定义了很多类似的请求格式。我数了一下,截止到目前最新的 2.3 版本,Kafka 共定义了多达 45 种请求格式。所有的请求都是通过 TCP 网络以 Socket 的方式进行通讯的
今天,我们就来详细讨论一下 Kafka Broker 端处理请求的全流程。
关于如何处理请求,我们很容易想到的方案有两个。
1.顺序处理请求。如果写成伪代码,大概是这个样子:
while (true) {
Request request = accept(connection);
handle(request);
}
这个方法实现简单,但是有个致命的缺陷,那就是吞吐量太差。由于只能顺序处理每个请求,因此,每个请求都必须等待前一个请求处理完毕才能得到处理。这种方式只适用于请求发送非常不频繁的系统
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Kafka核心技术与实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(36)

  • cricket1981
    双队列设计,分别存放数据类和控制类请求,每次先处理完所有控制类请求再处理数据类请求。
    2019-07-27
    1
    4
  • 明翼
    有两种方法:1 是直接替换数据处理队列中的最前面的数据进行处理,处理完控制队列,再将这个消息插队到队头;2 双队列设计,不过双队列,如果先处理控制消息,如果一直来控制消息,数据队列的消息岂不会被延迟很大;

    关于复制一套,我看了下面评论,我和部分网友的理解不一样,我觉得是复制一套网络线程持+中间队列+IO线程池;也就是有两个网络线程池,+2个中间队列,和2套IO线程持;

    网络线程池作用将数据分发到中间队列,和接受IO线程池的处理结果回复给客户端。我理解为什么要加这个中间队列是为了将网络处理的线程数和IO处理的线程数解耦,达到高性能和资源少占用的目的。

    作者回复: 我觉得不错:)

    2019-07-28
    3
  • Sunney
    老师您好,这两天做项目遇到一个问题想咨询一下,对于网络摄像头的视频流数据和抓拍到的照片数据,kafka应该如何传输呢?

    作者回复: 相同的方法,都要传输字节数组。你需要找到合适的方法把你的视频流数据或照片编码成字节序列。当然Kafka其实并不适合传输特别大的消息,因此你可以评估一下是否真的需求传视频本身?

    2019-07-29
    2
    2
  • ban
    老师,社区完全拷贝了这张图中的一套组件,实现了两类请求的分离。也就是说,Kafka Broker 启动后,会在后台分别创建网络线程池和 IO 线程池,它们分别处理数据类请求和控制类请求。

    上面这段话不太懂,意思是说:分别建立两套组件(A套 网络线程池IO线程池:负责处理数据类请求)、(B套 网络线程池IO线程池:负责处理控制类请求),这样理解对吗?

    作者回复: 嗯嗯,差不多是这个意思

    2019-07-28
    2
  • 电光火石
    优先级队列方案,可以开两个队列,分别处理,前面的监听端口不需要重新构建,只是后面的处理线程不同即可。
    另外,想问一下:
    1. 为什么当时kafka做的时候,没有考虑使用netty作为通信框架?
    2. 对IO这一块的处理比较感兴趣,老师可以介绍一下broker的入口类吗,想去看一下源码
    谢谢了!

    作者回复: 1. Kafka社区当初主要是为了jar依赖的问题而选择不使用netty,转而使用Java NIO的
    2. Broker入口类是kafka.server.KafkaServer.scala

    2019-07-27
    2
  • lmtoo
    小结部分的图片把数据类请求放到了网络线程池中,而控制类请求放到了IO线程池,弄反了吧;我觉得社区的决定是正确的,这两类请求分离之后,职责更明确了
    2019-07-27
    2
    2
  • 拾光
    为什么不直接将Acceptor线程收到的请求存入共享队列,而要引入网络线程池来存?

    作者回复: 我认为就是单纯地想要在做一层生产者-消费者分离

    2019-12-03
    1
  • 我理解Acceptor是用来接收连接的(三次握手),连接成功后把读写请求的Socket提交到网络线程池,网络线程池中的线程通过Selector收到读请求后,从内核读取消息数据,然后再把待处理消息数据放入共享请求队列中。共享请求队列应该是多生产者多消费者模式(这里如何设计比较关键)。io线程池从共享请求队列中取出消息处理,处理完成再把响应提交到网络线程池中,由网络线程池发送至客户端。这里的共享请求队列为什么不直接使用io线程池自带的工作队列呢?另外控制类请求单独走不同线程池处理比较合理。
    2019-07-30
    1
  • Riordon
    数据类请求和控制类请求的分离,我理解的是多开一套端口,实现一套网络线程池+IO线程池?不对吗?
    Acceptor线程:公平转发请求到网络线程
    网络线程池:将请求放入共享队列
    IO线程池:从共享队列取出请求,执行真正的IO
    2019-07-27
    1
  • 飞翔
    老师 请问有多少线程 在处理请求响应队列里的response消息呀

    作者回复: 网络线程池的个数

    2019-11-13
  • 飞翔
    老师 kafka 为什么不用reactor 最后一种模式 把用boss reactor 和work reactor 模型 而用较简单的第一种reactor
    2019-11-13
  • 注定非凡
    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 :无原则的平等,会造成混乱

    社区采取的方案是,同时创建两套完全样的组件,实现两类请求的分离。
    2019-11-07
  • 朱东旭
    胡老师您好,为什么有时候听到epoll,有时候听到reactor,这俩有啥区别。。

    作者回复: 不是一个层级的东西。epoll是一种IO模型,而Reactor是一种IO处理模式(IO pattern)。可以这么说:我们可以使用epoll来实现Reactor

    2019-11-02
  • 云师兄
    老师能否解答下kafka要分成网络线程和io线程?像tomcat这类请求模型中,网络线程也是执行线程,kafka大费周章,除了延迟请求,还有其他目的吗

    作者回复: 我不是设计人员不好妄言:)直观的感受是,可能就是单纯地想把分发线程和处理线程分开吧

    2019-10-14
  • B+Tree
    reactor模式特别适合多客户端向服务端请求的场景,同样场景的还有redis
    2019-10-09
  • 代码搬运工
    控制类请求直接创建新的线程池执行。
    2019-09-17
  • AF
    老师可不可以这么理解,这一节其实就是讲的Kafka的网络模型?

    作者回复: 可以的:)

    2019-09-15
  • shjdwxy
    如果共享请求队列满了,会出现什么问题呢?

    作者回复: 相应的线程阻塞住,表现为请求处理延时增加

    2019-09-14
  • DFighting
    优先级队列就算解决了队列满的问题也可能造成数据类请求饥饿的问题,既然两者是不同类型的请求,我还是觉得分开设计会避免不少的问题,为以后的优化带来空间,不过有一个问题,控制类请求和数据类请求操作的对象或多或少肯定会有重合,遇到冲突的话现在是怎么解决的呢?
    2019-09-09
  • Algoric
    Acceptor单线程是不是存在单点问题?且单线程如果并发量过大会不会出现瓶颈?Netty的Acceptor应该也是使用了线程池吧,希望可以解答一下

    作者回复: 由于Acceptor线程只接收请求然后转发,因此非常轻量级。通常情况下都不是瓶颈。你可以监控kafka.network:type=Acceptor,name=AcceptorBlockedPercent,listener={listenerName}来看看Acceptor线程的繁忙程度

    2019-09-07
收起评论
36
返回
顶部