我正在尝试使用在Kubernetes上运行的Apache Spark 2.3 Scala API扩展结构化流管道。工作的基本流程是这样的:
我在Kubernetes上运行,并配置了一个集群,其中包含30个执行器,每个执行器具有3个内核。 Kafka当前每个源ID每秒流式传输600000个指标,并配置了600个分区。我正在尝试将所有这些汇总到10个不同的输出中(即每个输出汇总由60000个不同的源ID组成)。我每10秒就有一次管道触发器来处理来自Kafka的〜6,000,000条记录。我的聚合窗口是1分钟不重叠的,并且我的水印设置为30秒。理想情况下,我希望使用更长的水印来解释延迟到达的数据,但是删除重复/水印阶段似乎是一个瓶颈,尤其是在调用垃圾收集器时。这是我最近运行的管道中的一些数据:
Processed And Input Rows Per Second
该图显示,管道在每秒大约8-9分钟的时间内保持每秒输入行的速度,但随后橙色线下降到绿色线(时间轴上的〜10:01)以下,并且管道很难时间跟上输入数据速率。我查看了Spark UI,了解了为什么会出现速度下降的线索,并发现在执行重复复制/水印阶段,一名执行者需要55秒来执行GC。以下是该阶段的摘要统计信息以及事件时间轴的放大图:
我尝试了here建议的多种技术,但结果却不尽相同。特别是:
其余的内存建议类似于“尝试修改此参数或该参数”,但是尝试每个排列都很困难,并且没有指出我应该期待的行为。有人可以指出我下一步的方向吗?我觉得GC的55秒是不合理的,应该有一些方法可以对其进行调整,以免我的工作受到1位执行者的阻碍。
答案 0 :(得分:1)
因此,当我脑海中浮现出新的解决方案时,我应该早点回答此问题,但最终我做了一些事情,从而减少了垃圾回收时间。我不记得所有有助于解决此问题的文档资源,但是我花了很多时间研究SO,gceasy建议和一般Java GC文献。无论如何,这就是最终的帮助:
因此,这是我正在使用的最后一组JVM参数。我希望这会有所帮助。
-XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:InitiatingHeapOccupancyPercent=35 -XX:+UseStringDeduplication -XX:ConcGCThreads=1 -XX:ParallelGCThreads=5