Kafka 设计详解之网络通信

前言

Kafka 是 LinkedIn 开发的一个分布式的消息中间件。由于其高吞吐量、可水平扩展等特性,目前被广泛使用,已经是目前大数据生态系统中不可或缺的一环,有关其详细介绍可以查看官方的文档。Kafka 的流行源于他优秀的设计,如依靠磁盘(以及操作系统的 Page Cache)而不是内存来存储队列数据、充分使用零拷贝(zero-copy)以减少数据在不同内存空间间的拷贝、数据尽可能的使用顺序读写等。今天准备深度解析 kafka 的网络通信模块,来学习下实现一个高吞吐量的系统要设计一个怎么样的网络通信机制。

网络通讯协议

作为一个消息队列,涉及的网络通信主要有两块:

  • 消息生产者与消息队列服务器之间(Kafka 中是生产者向队列「推」消息)
  • 消息消费者与消息队列服务器之间(Kafka 中是消费者向队列「拉」消息)

要实现上述的网络通信,我们可以使用 HTTP 协议,比如服务端内嵌一个 jetty 容器,通过 servlet 来实现客户端与服务端之间的交互,但是其性能存在问题,无法满足高吞吐量这个需求。要实现高性能的网络通信,我们可以使用更底层的 TCP 或者 UDP 来实现自己的私有协议,而 UDP 协议是不可靠的传输协议,毕竟我们不希望一条消息在投递或者消费途中丢失了,所以 Kafka 选择 TCP 作为服务间通讯的协议。

网络 IO 模型

谈到网络通信,绕不过 IO 模型,IO 模型主要是同步与异步,阻塞与非阻塞之间进行选择。

Kafka 的生产者同时实现了同步和异步两种类型的客户端(即:向服务端发完请求后可以一直等待响应也可以继续干后面的事),其异步客户端实现方式是通过线程池加回调函数。

Kafka 的服务端使用了 NIO 的 IO 多路复用技术,是非阻塞的 IO, kafka 的早期版本中,服务端是通过同步的方式处理客户端请求,最新版本是通过异步的方式进行的。

Kafka 自带的消费者是通过同步阻塞的方式进行数据拉取的,当然如果需要异步处理,可以自己另外写一个异步消费者。

Reactor 线程模型

Kafka 采用的是 Reactor 多线程模型,即通过一个 Acceptor 线程处理所有的新连接,通过多个 Processor 线程对请求进行处理(解析协议、封装请求并转发)。在早期版本中,对请求的处理在 Processor 线程中同步进行,也就是说,有多少个 Processor 线程就有多少个处理请求的线程。在新版本中,kafka 新增了一个 Handler 模块,通过指定的线程数对请求进行专门处理,Handler 与 Processor 之间通过一个 block queue 进行连接。线程模型如图:

kafka 线程模型

网络通信流程剖析

Kafka 的整个网络通信框架并非一成不变,从早期版本到现在经历了一些变化,下面我们通过分析早期的版本与最新版本的网络通信流程,了解其演变过程,以供自己在设计系统的网络通信时的一些参考。

早期版本(0.7)

Kafka 以 NIO 作为网络通信的基础,其通过将许多 socket 连接注册到一个 Selector 监听,可以只用一个线程就能管理很多的连接,减少了大量线程的系统开销。

早期版本的 kafka 的网络通信实现是一个简单的 Reactor 多线程模型,如图:


kafka 早期版本网络通信流程(白色虚线框内是一个 Processor 线程内部做的工作)
  1. 客户端向服务端发起请求时,Accept 负责接受这个 TCP 连接,连接成功后传递给其中一个 Processor 线程(先添加到 Processor 线程中的内部新连接队列)。
  2. Processor 线程收到该新连接后(从新连接队列中 poll),将其注册到自身的 Selector 中,监听其 READ 事件。
  3. 每当 Client 在这个连接上写入数据,就会触发 Processor 线程中 Selector 监听的 READ 事件,这时该线程会读出连接中的元数据,根据协议(Handler Mapping)调用相应的 Handler 进行处理
  4. Handler 处理完成后,可能会有返回值需要返回给客户端(如 Fetch 请求就需要返回具体内容给客户端),这时将 Handler 返回的 Response 绑定到连接上(SelectionKey.attach 方法),同时将这个连接的监听事件从 READ 转为 WRITE。
  5. Selector 监听到刚才注册的 WRITE 事件,将连接中绑定的 Response 发送。

个人理解 4、5 两步可以合并,即如果 Handler 有返回值,就直接返回,个人猜测 kafka 这样设计可能是出于整个架构上更加清晰优美的目的。

新版本

新版 Kafka 也是以 NIO 作为网络通信的基础,也是用 Reactor 多线程模型,所不同的是新版把具体业务处理模块(Handler 模块)独立出去,用单独的线程池进行控制。具体如下图:

kafka 新版本网络通信流程

新版本分离出 Handler 模块,我理解的好处有以下几个:

  • 可以单独指定 Handler 的线程数量,便于调优和管理
  • 可以避免一个超大请求堵住整一个 Processor 线程的情况
  • 因为 Request 与 Handler、Handler 与 Response 之间都是通过队列进行连接,所以彼此是解耦的,可以让请求变为异步,对系统的性能会有提升

总结

本文通过分析 kafka 的网络通信设计对网络编程进行了一次学习,笔者之后又对 netty 的网络通信进行了了解,发现大部分也类似,可见目前的高性能的网络通信可能存在「最佳实践」,不过真正在设计一个系统的网络通信时,还有很多工程上的问题需要解决,有许多的「坑」,很容易为系统埋下定时炸弹,因此,我看很多大牛都建议不要自己去实现网络通信模块,因为 netty 已经足够优秀了。

最后,如果读者有兴趣看 kafka 的源码,又对 scala 不是很熟悉,可以先看 jafka 的代码,它是早期 kafka 版本的 java 克隆版。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • kafka的定义:是一个分布式消息系统,由LinkedIn使用Scala编写,用作LinkedIn的活动流(Act...
    时待吾阅读 5,234评论 1 15
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,544评论 25 707
  • 测测孩子是属于视觉型,听觉型还是动觉触觉型呢? 以下每个问题中请选择一下答案,在你选定的字母上画圈。 1、 孩...
    喜宝小丸子阅读 23,334评论 0 1
  • 我听见北屋一声响,似乎是放碗碟的声音。儿子在小饭桌已经吃过午饭了,回家又吃了个粽子。肚子应该吃不下了呀。我便随口问...
    铅笔芒种阅读 254评论 0 2