java - 为什么在记录、生产者和消费者数量不变的 Kafka 经纪人中 GC 时间会增加?

标签 java apache-kafka garbage-collection

我使用的是 Kafka 2.1.0。

我们有一个包含 5 个代理(r5.xlarge 机器)的 Kafka 集群。我们经常观察到 GC 时间增加太多,而传入消息的速率没有任何变化,严重影响了集群的性能。现在,我不明白是什么导致 GC 时间突然增加。

我已经尝试了一些改进很少的东西,但我并不真正理解它们背后的原因。

export KAFKA_HEAP_OPTS="-Xmx10G -Xms1G"
export KAFKA_JVM_PERFORMANCE_OPTS="-XX:MetaspaceSize=96m -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=16M -XX:MinMetaspaceFreeRatio=50 -XX:MaxMetaspaceFreeRatio=80"

我想了解在 Kafka 代理中调整 GC 时最重要的参数。 看到上面的配置,我哪里错了?可以做些什么来纠正这个问题?

所有生产者和消费者都工作正常,传入消息的速率保持相当稳定。到目前为止,我们还没有弄清楚 GC 时间突然增加背后的任何模式,这似乎是随机的。

更新

经过进一步分析,发现每秒的数据量确实有所增加。其中一个主题将消息输入从大约 10 KBps 增加到 200 KBps。但我相信 Kafka 可以轻松处理这么多数据。

有什么我想念的吗??

Grafana 快照 enter image description here

最佳答案

我会首先查看问题是否是 其他 而不是 GC 调整问题。这里有几种可能性:

  • 硬内存泄漏会导致 GC 时间增加。 GC 完成的工作主要是通过跟踪和复制可达对象来完成的。如果存在泄漏,那么越来越多的对象将(错误地)可达。

  • 保持太多对象可访问的缓存也会增加 GC 时间。

  • 过度使用引用类型、终结器等可能会增加 GC 时间。

我将启用 GC 日志记录,并查找 GC 报告的内存和空间使用模式。如果您怀疑内存泄漏是因为从长远来看内存利用率呈上升趋势,请转到下一步并使用内存配置文件来追踪泄漏。

无论哪种方式,在尝试解决问题之前了解导致问题的原因都很重要。


After some further analysis, it turns out there was indeed some increase in the amount of data per sec. One of the topics had increased message input from around 10 KBps to 200 KBps. But I believed that Kafka could easily handle this much of data.

很有可能。然而,吞吐量增加 20 倍将不可避免地导致更多对象被创建和丢弃……并且 GC 将需要更频繁地运行来处理这个问题。


How come just 200 Kbps of data divided among 5 brokers was able to break GC.

是什么让您认为您已经“破坏”了 GC? GC 中 15% 的时间并不意味着它已损坏。

现在,我可以想象 GC 可能难以达到您的 20 毫秒最大暂停时间目标,并且可能因此触发偶尔的完整 GC。您的暂停时间目标是“雄心勃勃的”,尤其是当堆可能增长到 10GB 时。我会建议减小堆大小、增加暂停时间目标和/或增加 JVM 可用的物理内核数量。

By breaking I mean an increased delay in committing offsets and other producer and consumer offsets.

所以...您只是担心负载增加 20 倍会导致 GC 使用高达 15% 的可用 CPU。好吧,那没有坏。这是(IMO)预期的。垃圾收集器并不神奇。它需要使用 CPU 时间来完成它的工作。它要做的工作越多,它需要使用的 CPU 就越多。如果您的应用程序的工作负载涉及大量对象分配,则 GC 必须处理。

除了上述调优思路外,我怀疑您应该将 G1HeapRegionSize 大小设置得更小。根据"Garbage First Garbage Collector Tuning"根据 Monica Beckwith,默认情况下根据最小堆大小有 2048 个区域。但是你的设置会给 1G/16M == 64 个初始区域。

最后,如果您的总体目标是降低 GC 的 CPU 使用率,那么您应该使用 Throughput GC,而不是 G1GC。这将最小化 GC 开销。缺点是 GC 暂停最小化不再是目标,因此偶尔会出现长时间的暂停。

如果你打算继续使用 G1GC,建议使用最新版本的 Java;即 Java 11。(参见 "G1 Garbage Collector is mature in Java 9, finally")

关于java - 为什么在记录、生产者和消费者数量不变的 Kafka 经纪人中 GC 时间会增加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53959607/

相关文章:

go - 使用Golang连接kafka时如何设置zookeeper chroot路径?

c# - 如何查看一次垃圾回收的内容?

java - 无法启动 Apache Spark 2.1.1 的工作节点

java - @Id 在插入实体 bean 时不会自动设置

Java正则表达式匹配精确的单词

java - 无法使用 apache POI 在工作簿中创建新的 Excel 工作表

apache-kafka - 为什么Kafka消费者需要很长时间才能开始消费?

spring-boot - KafkaTemplate 线程安全吗

c# - 如何确保 StringBuilder 对象在多线程环境中被 GCed? (鉴于我不能使用 using 关键字)?

c# - 为什么 EF Core 2.2.6 不进行垃圾收集?