找回密码
 立即注册
搜索

分析:十张图,五个问题带你彻底理解 Kafka 架构调2022/6/23 16:26:49


1 了解K超高并发络架构是如何设计吗?我们知道 K 络通信架构使用到了 J NIO 以及 R 设计模式。我们先从整体上看一下完整的络通信层架构,如下图所示:加速器的相关资讯可以到我们网站了解一下,从专业角度出发为您解答相关问题,给您优质的服务!https://www.tiandiapp.com/




1)从上图中我们可以看出,K 络通信架构中用到的组件主要由两大部分构成:SS 和 RHP。

2)SS 组件是 K 超高并发络通信层中比较重要的子模块。它包含 A 线程、P 线程和 RC 等对象,都是络通信的重要组成部分。

3)RHP 组件就是我们常说的 IO 工作线程池,里面定义了若干个 IO 线程,主要用来执行真的请求处理逻辑。

01 A 线程在经典的 R 设计模式有个「D」的角色,主要用来接收外部请求并分发给下面的际处理线程。在 K 络架构设计中,这个 D 就是「A 线程」,用来接收和创建外部 TCP 连接的线程。在 B 端每个 SS 例只会创建一个 A 线程。它的主要功能就是创建连接,并将接收到的 R 请求传递给下游的 P 线程处理。



1)我们可以看出 A 线程主要使用了 J NIO 的 S 以及 SC 的方式循环的轮询准备就绪的IO事件。

2)将 SSC 通道注册到S 上,并关注络连接创事件:SKOP_ACCEPT。

3)事件注册好后,一旦后续接收到连接请求后,A 线程就会指定一个 P 线程,并将该请求交给它并创建络连接用于后续处理。

02 P线程A只是做了请求入口连接处理的,那么,真正创建络连接以及分发络请求是由 P 线程来完成的。而每个 P 线程在创建时都会创建 3 个队列。

1)C 队列:它主要是用来保存要创建的新连接信息,也就是SC 对象,目前是硬编码队列长度大小为20。每当 P 线程接收到新的连接请求时,都会将对应的 SC 对象放入队列,等到后面创建连接时,从该队列中获取 SC,然后注册新的连接。

2)R 队列:它是一个临时的 R 队列,当 P 线程将 R 返回给 C 之后,要将 R 放入该队列。它存在的意义:由于有些 R 回调逻辑要在 R 被发送回 R 发送方后,才能执行,因此需要暂存到临时队列。

3)RQ 队列:它主要是存放需要返回给R 发送方的所有 R 对象。每个 P 线程都会维护自己的 R 队列。





03 RHP线程池A 线程和 P 线程只是请求和响应的「搬运工」,而「真正处理 K 请求」是KRHP线程池,在上面络超高并发通信架构图,有两个参数跟整个流程有关系,分别是「」、「」。其中 就是IO 工作线程池的大小配置。



下面我们结合 K 超高并发络架构图来讲解下一个完整请求处理核心流程:

1)C 发送请求给 A 线程。

2)A 线程会创建 NIO S 对象,并创建 SSC 通道例,然后将 C 和 OP_ACCEPT 事件绑定到 S 多路复用器上。

3)A 线程默认创建3个P 线程参数:, 并轮询的将请求对象 SC 放入到连接队列中。

4)这时候连接队列就源源不断有请求数据了,然后不停地执行 NIO P, 获取对应 SC 上已经准备就绪的 IO 事件。

5)P 线程向 SC 注册了 OP_READOP_WRITE 事件,这样 客户端发过来的请求就会被该 SC 对象获取到,具体就是 CR 方法。

6)这个时候客户端就可以源源不断进行请求发送了,服务端通过 S NIO P 不停的获取准备就绪的 IO 事件。

7)然后根据C中获取已经完成的R对象,构建R对象,并将其存入到 R 的 RQ 请求队列中 。

8)这个时候就该IO 线程池上场了,KRH 线程循环地从请求队列RQ 中获取 R 例,然后交由KA 的方法,执行真正的请求处理逻辑,并比较终将数据存储到磁盘中。

9)待处理完请求后,KRH 线程会将 R 对象放入 P 线程的 R 队列。

10)然后 P 线程通过 R 中的 PID 不停地从 R 队列中来定位并取出 R 对象,返还给 R 发送方。

2 了解K高吞吐日志存储架构是如何设计吗?对于 K 来说,它主要用来处理海量数据流,这个场景的特点主要包括:

1) 写操作:写并发要求非常高,基本得达到百万级 TPS,顺序追加写日志即可,需考虑更新操作。



2)读操作:相对写操作来说,比较简单,只要能按照一定规则高效查询即可,支持(或者时间戳)读取。



根据上面两点分析,对于写操作来说,直接采用「顺序追加写日志」的方式就可以满足 K 对于百万TPS写入效率要求。

如何解决高效查询这些日志呢我们可以设想把消息的 O 设计成一个有序的字段,这样消息在日志文件中也就有序存放了,也不需要额外引入哈希表结构,可以直接将消息划分成若干个块,对于每个块我们只需要索引当前块的首条消息的 O ,这个是不是有点二分查找算法的意思。即先根据 O 大小找到对应的块,然后再从块中顺序查找。如下图所示:



这样就可以速定位到要查找的消息的位置了,在 K 中,我们将这种索引结构叫做「稀疏哈希索引」。

上面得出了 K 比较终的存储现方案,即基于顺序追加写日志 +稀疏哈希索引。

接下来我们来看看 K 日志存储结构:



从上图看出来,K 是基于「主题 +分区 + 副本 + 分段 + 索引」的结构进行日志存储的。

了解了整体的日志存储架构,我们来看下 K 日志格式,K 日志格式也经历了多个版本迭代,这里我们主要看下V2版本的日志格式:

通过上图可以得出:V2 版本日志格式主要是通过可变长度提高了消息格式的空间使用率,并将某些字段抽取到消息批次(RB)中,同时消息批次可以存放多条消息,从而在批量发送消息时,可以大幅度地节省了磁盘空间。

接下来我们来看看日志消息写入磁盘的整体过程如下图所示:

3 针对 K 线上集群部署方案, 你是怎么做的这里我们从架构师必备能力出发, 以电商平台为例讲述了 K 生产级容量评估方案该如何做如何让以及运维部门得到认可,获准你的方案。



详细可以深读:八大步骤带你深度剖析K生产级容量评估方案

4 针对 K 线上系统, 你是如何进行监控的?K 作为大型系统架构中重要的一环,有着举足轻重的作用,因此 K 集群的稳定性尤为重要,我们要对生产的 K 集群进行全方位的监控,一般线上系统可以从以下五个维度进行监控:

01 主机节点监控所谓主机节点监控就是监控 K 集群 B 所在节点机器的性能。主机节点监控对于 K 来说是比较重要的,因为很多线上环境问题首先就是由于主机的某些性能出现了问题。

因此对于 K 来说,主机监控通常是发现问题的首步,主要性能指标如下:

「机器负载(L)」、「CPU 使用率」、「内存使用率」、「磁盘 IO 使用率」、「络 IO 使用率」、「TCP 连接数」、「打开文件数」、「 使用情况」。

如果想要更好的监控主机性能的话,有以下两个教程可以学习和参考:



02 JVM 监控另一个重要的监控维度就是 JVM 监控。监控 JVM 进程主要是为了让你全面地了解K B 进程。

要监控JVM 进程,需要关注 3 个指标:

「监控F GC 发生频率和时长」、「监控堆上活跃对象大小」、「监控应用线程总数」

03 K 集群监控另外一个重要监控维度就是 K B 集群和各类客户端的监控,主要有3个方法:

1)查看 B 端重要日志:主要包括 B 端服务器日志 ,控制器日志以及主题分区状态变更日志 -。其中, 是比较重要的,如果你的 K 集群出现了故障,你要首时间查看 ,定位故障原因。



2)查看 B 端关键线程运行状态,例如:

L C 线程:日志压缩清理。一旦它挂掉了,所有 C 操作都会中断,但用户对此通常是感知的。



副本拉取消息的线程:主要执行 F 副本向 L 副本拉取消息的逻辑。如果它们挂掉了,系统会表现为 F 副本延迟 L 副本越来越大。



3)查看 B 端关键的 JMX 性能指标:主要有BIBO、NPAIP、RHAIP、URP、ISRSISRE、ACC 这几个指标。



04 K 客户端监控客户端监控主要是生产者和消费者的监控,生产者往 K 发送消息,此时我们要了解客户端机器与 B 机器之间的往返时延 RTT 是多少,对于跨数据中心或者异地集群来说,RTT 会更大,很难支撑很大的 TPS。

P角度:- 是需要重点关注的JMX指标,即消息生产请求的延时;另外 S 线程的运行状态也是非常重要的, 如果 S 线程挂了,对于用户是感知的,表象只是 P 端消息发送失败。

C角度:对于 C G,需要重点关注和指标,它表示 R 的频繁程度。另外还包括消息消费偏移量、消息堆积数量等。

05 B 之间的监控比较后一个监控维度就是 B 之间的监控,主要指副本拉取的性能。F 副本时拉取 L 副本的数据,此时我们希望拉取过程越越好。K 提供了一个特别重要的 JMX 指标,叫做「」,意思就是比如我们规定这条消息,应该在两个 B 上面保存,假设只有一个 B 上保存该消息,那么这条消息所在的分区就叫,这种情况是特别关注的,因为有可能造成数据的丢失。

另外还有一个比较重要的指标是「 」。在整个 K 集群中应该确保只能有一台机器的指标是1,其他全应该是0,如果发现有一台机器大于1,一定是出现脑裂了,此时应该去检查下是否出现了络分区。K本身是不能对抗脑裂的,完全依靠 Z 来做,但是如果真正出现络分区的话,也是没有办法处理的,应该让其速失败重启。

5 针对 K 线上系统, 你是如何进行调的?对 K 来说,「吞吐量」和「延时」是非常重要的化指标。

吞吐量 TPS:是指 B 端或 C 端每秒能处理的消息数,越大越好。

延时:表示从 P 端发送消息到 B 端持久化完成到 C 端成功消费之间的时间间隔。与吞吐量 TPS 相反,延时越短越好。

总之,高吞吐量、低延时是我们调 K 集群的主要目标。

01 提升吞吐量首先是提升吞吐量参数和措施:

















B

:表示 F 副本用多少个线程来拉取消息,默认1个线程。如果 B 端 CPU 资源很充足,适当增加该值「但不要超过CPU核数」,以加 F 副本的同步速度。这是因为在生产环境中,配置了 = 的 P 端影响吞吐量的首要因素就是副本同步性能。适当增加该值后通常可以看到 P 端吞吐量增加

:在ISR 中,如果 F 长时间未向 L 发送通信请求或同步数据,则该 F 将被踢出 ISR,该值默认为 30。

:单个A创建P处理器的线程个数,默认值为3, 可以适当提高该值为9。

:服务器用于处理请求的线程数,可能包括磁盘 IO,默认值是 8,可以适当提高该值为32。

调参数以避免频繁性的 F GC

















P

:表示消息批次大小,默认是 16。

如果设置太小,会导致频繁络请求,吞吐量下降;

如果设置太大,会导致一条消息需要等待很久才能被发送出去,增加络延时。

所以适当增加会提高吞吐量,建议从默认的16增加到512或者1M。

:RA 发送消息的缓冲区总大小,默认值是 32M,可以增加到 64M。

:表示批次缓存时间,如果数据迟迟未达到 , 等待之后就会发送数据。单位 ,默认值是 0,意思就是消息必须立即被发送。

如果设置的太短,会导致频繁络请求,吞吐量下降;

如果设置的太长,会导致一条消息需要等待很久才能被发送出去,增加络延时。

所以适当增加会提高吞吐量,建议10~100毫秒。

:默认是 ,不压缩,但是也可以使用 4 压缩,效率还是不错的,压缩之后可以减小数据量,提升吞吐量,但是会加大端的 CPU 开销。支持压缩类型:、、、4 和 。

设置=01,=0,化目标是吞吐量,不要设置 =「副本同步时间拉长」及开启重试「执行时间拉长」。







C

利用多线程增加整体吞吐量

:表示只要 B 端积攒了多少数据,就可以返回给 C 端。默认值1字节,适当增大该值为1或者更大。

:消费者获取服务器端一批消息比较大的字节数。一批次的大小受【 配置】或【 】影响,默认是50M。

:表示一次拉取数据返回消息的比较大条数大小,默认是 500 条。

分 区

增加分区来提高吞吐量

02 降低延时降低延时的目的就是尽量减少端到端的延时。

对比上面提升吞吐量的参数,我们只能调整 P 端和 C 端的参数配置。

对于 P 端,此时我们希望可以速的将消息发送出去,必须设置 =0,同时关闭压缩,另外设置= 1,减少副本同步时间。

而对于 C 端我们只保持 =1 ,即 B 端只要有能返回的数据,就立即返回给 C,减少延时。

03 合理设置分区数分区数不是越多越好,也不是越少越好,需要搭建完集群,进行压测,再灵活调整分区个数。

这里可以用 K 官方自带的脚本,对 K 进行压测。

1)生产者压测:---

2)消费者压测:---
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册