【问题标题】:Read IO size for Kafka fetch request读取 Kafka 获取请求的 IO 大小
【发布时间】:2019-09-11 07:39:44
【问题描述】:

发出获取请求时 - 响应大小受到各种 Kafka 参数的限制,并且它们有据可查。但我的问题是——核心的读取 IO 大小是多少。进程必须打开段文件并发出 read() 操作并将数据放入内存。问题是 - 这个 read() 的大小是多少 - 它是一个固定数字还是等于 - max.partition.fetch.bytes?如果是这样,那么如果分区有足够的数据,一个读取 IO 将获得足够的数据来为该分区提供消费者。我尝试查看源代码,但无法弄清楚这个大小。

我这样做的原因是 - 我正在对我的 Kafka 日志文件系统进行基准测试,对于消费者,我想看看文件系统在多大的读取 IO 大小下表现得更好,并想看看 Kafka 获取/轮询是否显示相同的模式。

【问题讨论】:

    标签: apache-kafka


    【解决方案1】:

    您的问题有两个 I/O:磁盘 i/o 和网络 i/o

    磁盘 i/o: Kafka 利用文件系统进行存储和缓存。

    如果您正在寻找核心磁盘 I/O 操作大小,那么它是典型的块大小,并且大多数现代操作系统由 PageCache 定义的块大小通常高达 4096 字节(例如 $getconf PAGESIZE 显示大小在您的服务器上)

    总结:虚拟内存页面映射到文件系统块,文件系统块映射到块设备扇区。

    参考代码LogSegment.scala 内部使用 FileRecord.java,它使用 FileSystem 调用。

    Network i/o 接下来是 Consumer Fetch 请求,

    大多数情况下,Consumer FetchRequest 从特定领导分区代理上的(热数据)PageCache 中获取。根据您的消费者 Kafka 参数(例如,Min/MaxBytes 和 maxWaitMs),它会填充来自 PageCache 的 NIC 请求并通过网络传输。

    参考代码:Fetcher.java (ConsumerNetworkClient)Client.send() 并等待网卡响应。

    pagecache 和 sendfile 的这种组合意味着在 Kafka 集群上,消费者大多被赶上,您将不会看到磁盘上的任何读取活动,因为它们将完全从缓存中提供数据。因为Kafka使用零拷贝数据传输(Broker → Consumer)

    因此,大多数性能调整(除了用于页面缓存和磁盘 i/o 的可用内存)您可以使用消费者参数,例如最小等待时间和数据包的最大缓冲区大小。

    以下是对 Consumption 进行性能调整时需要考虑的一些要点:

    【讨论】:

      【解决方案2】:

      您可以在此处查看默认的ConsumerConfig

      https://github.com/apache/kafka/blob/2.3/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerConfig.java

      以及消费者如何从 kafka 主题中获取数据,在Fetcher.java中有很好的定义

      final FetchSessionHandler.FetchRequestData data = entry.getValue();
                  final FetchRequest.Builder request = FetchRequest.Builder
                          .forConsumer(this.maxWaitMs, this.minBytes, data.toSend())
                          .isolationLevel(isolationLevel)
                          .setMaxBytes(this.maxBytes)
                          .metadata(data.metadata())
                          .toForget(data.toForget())
                          .rackId(clientRackId);
      

      https://github.com/apache/kafka/blob/2.3/clients/src/main/java/org/apache/kafka/clients/consumer/internals/Fetcher.java#L237

      它具有每个属性的默认值,这些默认值被配置中的用户输入值覆盖。

      【讨论】:

      • 感谢 Nishu - 是的,这些限制了获取的总字节数。我正在查看更多关于给定代理中的分区。例如,我有一个分区,我有大约 1GB 的未读数据,一个提取请求来自一个 max.partition.fetch.bytes 大小为 1MB 的消费者。如果 Kakfka 尊重 1MB,那么在代理端 - 将触发多少读取系统调用来获取 1MB?它会是 1MB 的大胖读取 IO,还是会是 n 个 65K 读取 x 大小为 y 的读取 IO。
      • kafka 严重依赖内存映射段文件,这意味着它将由操作系统进行读取 - 这很难说。另外 - 如果数据是最近的,它实际上会从内存中提供服务(页面缓存)
      • 嗨 Radai - 非常感谢,是的,它做了很多 mmap 操作,但我认为主日志不是通过 mmap 读取的,否则它不能大量使用缓存。它使用 NIO 并通过通道读取 - ByteBuffer 的大小应该定义读取长度。读取可能不会导致对磁盘的物理 IO - 但它仍会对操作系统进行读取调用。我正在寻找的是读取请求的大小。它是依赖于配置参数还是固定值 int?
      猜你喜欢
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      相关资源
      最近更新 更多