Sea*_*n O 5 garbage-collection jvm apache-spark kubernetes apache-spark-sql
我正在尝试使用在 Kubernetes 上运行的 Apache Spark 2.3 Scala API 来扩展结构化流管道。工作的基本流程是这样的:
我在 Kubernetes 上运行并配置了一个集群,其中包含 30 个执行程序,每个执行程序有 3 个内核。Kafka 目前每个源 id 每秒流式传输 600000 个指标,并配置了 600 个分区。我正在尝试将它们全部聚合为 10 个不同的输出(即,每个输出聚合包含 60000 个不同的源 ID)。我每 10 秒就有一次管道触发器来处理来自 Kafka 的约 6,000,000 条记录。我的聚合窗口是 1 分钟不重叠,我的水印设置为 30 秒。理想情况下,我想要更长的水印来解释迟到的数据,但删除重复项/水印阶段似乎是一个瓶颈,尤其是在调用垃圾收集器时。以下是我最近运行的管道的一些数据:
该图显示管道每秒跟上输入行大约 8-9 分钟,但随后橙色线下降到绿线以下(时间轴上的~10:01)并且管道很难跟上与输入数据速率。我查看了 Spark UI 以寻找有关为什么会发生减速的线索,并发现一个执行程序在删除重复项/水印阶段需要 55 秒来执行 GC。以下是舞台的汇总统计数据和事件时间线的放大图:
我尝试了此处建议的多种技术,但结果喜忧参半。特别是:
其余的内存建议就像“尝试修改这个参数或那个参数”,但是很难尝试每一个排列,而且它没有表明我应该期待什么行为。有人可以指出我下一步要遵循的方向吗?我觉得 55 秒的 GC 是不合理的,应该有一些方法来调整它,这样我的工作就不会受到 1 个执行者的阻碍。
因此,当我对解决方案记忆犹新时,我应该早点回复这个问题,但我最终做了一些有助于减少垃圾收集时间的事情。我不记得帮助我解决这个问题的所有文档来源,但我花了很多时间研究 SO、gceasy 建议和一般 Java GC 文献。无论如何,这就是最终有帮助的:
这是我最终使用的 JVM 参数集。我希望这有帮助。
-XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:InitiatingHeapOccupancyPercent=35 -XX:+UseStringDeduplication -XX:ConcGCThreads=1 -XX:ParallelGCThreads=5
Run Code Online (Sandbox Code Playgroud)