数据采集 动态与静态分配中的Spark作业

问题描述 投票:1回答:2

我有一个Dataproc集群:

master - 6cores | 32克

工人{0-7} - 6cores | 32克

最大分配:内存:24576,vCores:6

有两个火花流工作要一个接一个地提交

首先,我尝试使用默认配置spark.dynamicAllocation.enabled=true提交

在30%的案例中,我看到第一份工作几乎占据了所有可用内存,第二份工作排队并等待资源多年。 (这是一个流媒体工作,每批次都占用了一小部分资源)。

我的第二次尝试是改变动态分配。我提交了相同配置的相同两个作业:

spark.dynamicAllocation.enabled=false
spark.executor.memory=12g
spark.executor.cores=3
spark.executor.instances=6
spark.driver.memory=8g

令人惊讶的是在Yarn UI中我看到:

7个运行容器,为第一个作业分配84g内存。

3个运行容器,内存分配36g,第二个作业72g预留内存

在Spark UI中,第一个作业有6个执行程序和驱动程序,第二个作业有2个执行程序和驱动程序

在没有动态分配和相同配置的情况下重试(删除以前的作业并提交相同的作业)后,我得到了完全不同的结果:

5个容器59g两个作业的内存分配和第二个作业的71g预留内存。在spark UI中,我在两种情况下都看到了4个执行器和驱动程序。

我有一些问题:

  1. 如果dynamicAllocation = false,为什么纱线容器的数量与执行者的数量不同? (首先我认为额外的纱线容器是一个驱动器,但它的内存不同。)
  2. 如果dynamicAllocation = false,为什么Yarn不会根据我的确切要求创建容器 - 两个作业的6个容器(spark executors)。为什么使用相同配置的两次不同尝试会导致不同的结果?
  3. 如果dynamicAllocation = true - 低消耗内存spark工作如何可能控制所有Yarn资源

谢谢

apache-spark spark-streaming yarn google-cloud-dataproc
2个回答
4
投票

Spark和YARN调度非常混乱。我将以相反的顺序回答问题:

3)您不应该在Spark流工作中使用动态分配。

问题是,只要有大量的任务要运行,Spark就会不断要求YARN提供更多的执行程序。一旦Spark作业获得执行程序,它就会保留它直到执行程序空闲1分钟(当然可配置)。在批处理作业中,这是可以的,因为通常会有大量连续积压的任务。

但是,在流媒体作业中,每个微批处理开始时都会出现一系列任务,但执行程序在大多数情况下实际上处于空闲状态。因此,流媒体作业将抓住许多不需要的执行者。

为了解决这个问题,旧的流API(DStreams)有自己的动态分配版本:https://issues.apache.org/jira/browse/SPARK-12133。这个JIRA有更多背景知道为什么Spark的批量动态分配算法不适合流式传输。

但是,Spark Structured Streaming(可能是您正在使用的)不支持动态分配:https://issues.apache.org/jira/browse/SPARK-24815

tl; dr Spark根据其任务积压请求执行程序,而不是基于使用的内存。

1&2)@Vamshi T是对的。每个YARN应用程序都有一个“Application Master”,它负责为应用程序请求容器。每个Spark作业都有一个app master,用于代理驱动程序对容器的请求。

您的配置似乎与您在YARN中看到的不匹配,因此不确定那里发生了什么。你有8名工人,24克给了YARN。使用12g执行程序,每个节点应该有2个执行程序,总共16个“插槽”。应用程序主机+6个执行程序应该是每个应用程序7个容器,因此两个应用程序应该适合16个插槽。

我们将app master配置为具有更少的内存,这就是为什么应用程序的总内存不是12g的干净倍数的原因。

如果您希望两个应用程序同时安排所有执行程序,则应设置spark.executor.instances = 5。

假设您正在使用结构化流,您也可以在同一个Spark应用程序中运行两个流作业(从驱动程序的不同线程提交它们)。

有用的参考:


1
投票

我也注意到了我的经历中的类似行为,这是我观察到的。首先,纱线的资源分配取决于提交作业时群集上的可用资源。当两个作业几乎同时以相同的配置提交时,yarn会在作业之间平均分配可用资源。现在,当您将动态分配投入到混合中时,事情变得有点混乱/复杂。现在在你的情况下:

7个运行容器,为第一个作业分配84g内存。 - 你有7个容器,因为你要求6个执行器,每个执行器有一个容器,额外的一个容器用于应用程序Master

3个运行容器具有36g内存分配和72g预留内存用于第二个作业 - 由于第二个作业在一段时间后提交,Yarn分配了剩余资源... 2个容器,每个执行器一个,另外一个用于应用程序主机。

您的容器永远不会与您请求的执行程序匹配,并且总是比您请求的执行程序数多一个,因为您需要一个容器来运行您的应用程序主机。

希望能回答你的部分问题。

© www.soinside.com 2019 - 2024. All rights reserved.