我在 kafka 集群(3 个 Brokers)中对 1000 万条记录进行负载测试时遇到运行时异常,每次遇到此问题后,broker 都会崩溃。在我最初的分析过程中,我认为问题可能与 vm.max_map_count 的默认值(65K)有关,但我已将其增加到更高的值 400K。我重新测试了负载,代理在处理 3 到 400 万条记录的过程中再次崩溃。
我对进程和操作系统采样进行了更好的监控,并且在负载测试期间没有看到任何性能异常。此外,服务器的数据目录中还留有大量磁盘空间。每个代理的堆内存设置为 6GB(xmx 和 xms),60 GB RAM Linux 服务器。
我开始看到kafka主要版本升级到3.x后。有人遇到过这个问题吗?我是否需要通过 3.x 测试如此高的负载来进行任何性能调整。
Java Version:
openjdk version "11.0.8" 2020-07-14 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.8+10-LTS)
Error while appending records to LoadTestingTopic in dir /broder/log (org.apache.kafka.storage.internals.log.LogDirFailureChannel)
java.io.IOException: Map failed
at java.base/sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:1016)
at org.apache.kafka.storage.internals.log.AbstractIndex.createMappedBuffer(AbstractIndex.java:466)
at org.apache.kafka.storage.internals.log.AbstractIndex.createAndAssignMmap(AbstractIndex.java:104)
at org.apache.kafka.storage.internals.log.AbstractIndex.<init>(http://AbstractIndex.java:82)
at org.apache.kafka.storage.internals.log.OffsetIndex.<init>(http://OffsetIndex.java:69)
at org.apache.kafka.storage.internals.log.LazyIndex.loadIndex(LazyIndex.java:239)
at org.apache.kafka.storage.internals.log.LazyIndex.get(LazyIndex.java:179)
at kafka.log.LogSegment.offsetIndex(LogSegment.scala:67)
at kafka.log.LogSegment.canConvertToRelativeOffset(LogSegment.scala:130)
at kafka.log.LogSegment.ensureOffsetInRange(LogSegment.scala:177)
at kafka.log.LogSegment.append(LogSegment.scala:157)
at kafka.log.LocalLog.append(LocalLog.scala:439)
at kafka.log.UnifiedLog.append(UnifiedLog.scala:911)
at kafka.log.UnifiedLog.appendAsLeader(UnifiedLog.scala:719)
at kafka.cluster.Partition.$anonfun$appendRecordsToLeader$1(Partition.scala:1313)
at kafka.cluster.Partition.appendRecordsToLeader(Partition.scala:1301)
at kafka.server.ReplicaManager.$anonfun$appendToLocalLog$6(ReplicaManager.scala:1210)
at scala.collection.StrictOptimizedMapOps.map(StrictOptimizedMapOps.scala:28)
at scala.collection.StrictOptimizedMapOps.map$(StrictOptimizedMapOps.scala:27)
at scala.collection.mutable.HashMap.map(HashMap.scala:35)
at kafka.server.ReplicaManager.appendToLocalLog(ReplicaManager.scala:1198)
at kafka.server.ReplicaManager.appendRecords(ReplicaManager.scala:754)
at kafka.server.KafkaApis.handleProduceRequest(KafkaApis.scala:686)
at kafka.server.KafkaApis.handle(KafkaApis.scala:180)
at kafka.server.KafkaRequestHandler.run(KafkaRequestHandler.scala:149)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.OutOfMemoryError: Map failed
at java.base/sun.nio.ch.FileChannelImpl.map0(Native Method)
at java.base/sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:1013)
此问题现已修复。
经过广泛调查,我们发现映射失败(OOM)是由特定主题引起的,其中日志段文件滚动速度太快。我们通过设置一个监控 KAFKA 数据日志目录的后台脚本来识别这一点。
看起来该高容量主题存在配置错误,其中,segment.ms 的值仅为 100,而不是 3 天。最终,KAFKA 在创建的每个段文件上创建了文件处理程序/文件描述符/打开文件,并且每个服务器允许的文件描述符/打开文件超出了在操作系统内核级别设置的限制。因此,我们在性能测试过程中最终遇到了“映射失败”(OOM) 和“打开文件过多”问题。将 log.segment.ms 更新到 3 天修复了这些问题。