我们有一个包含操作的管道,分为两个工作负载-Source -> Transform
在第一组中,并且是CPU密集型工作负载,它们被放在同一个插槽共享组中,比方说source
。还有Sink
,这是占用大量RAM的工作量,因为它使用批量上传并在内存中保存大量数据。它已发送到sink
插槽共享组。
此外,我们的Source -> Transform
工作负载和Sink
工作负载具有不同的并行度,因为第一个受源并行度限制。因此,例如,我们的Source -> Transform
并行度为50,而Sink
并行度等于78。我们有8个TM,每个TM具有16个内核(因此有插槽)。
在这种情况下,对于我们来说,理想的插槽分配策略似乎是为Source -> Transform
在每个TM上分配6-7个插槽,其余的-对于Sink
导致的CPU-RAM工作负载大致在所有TM上均匀分布。
所以,我想知道是否有一些配置设置可以告诉您平均分配插槽共享组吗?
我仅找到cluster.evenly-spread-out-slots配置参数,但是我不确定它是否实际上平均分配了插槽共享组,不仅是插槽-例如,我同时拥有10个Source -> Transform
任务的TM期望6或7。
因此,问题是是否可以告诉Flink在整个群集中平均分配插槽共享组?或者可能还有其他可能性?
Distribute a Flink operator evenly across taskmanagers似乎有点类似于我的问题,但是我主要是在询问插槽共享组的分配。该主题还仅包含使用cluster.evenly-spread-out-slots的建议,但此后可能有所改变。
答案 0 :(得分:0)
我曾经尝试实现这一点,但是问题是Flink没有提供启用操作员放置的功能。我可以接近的是使用.map(...).slotSharingGroup("name");
。正如有关“ Set slot sharing group”的文档所述:
设置操作的插槽共享组。 Flink将投入运营 保持相同的插槽共享组到同一插槽 在其他插槽中没有插槽共享组的操作。这个 可用于隔离插槽。插槽共享组继承自 如果所有输入操作都在同一插槽共享中,则输入操作 组。默认插槽共享组的名称为“默认”, 可以通过调用将操作显式放入该组 slotSharingGroup(“默认”)。
someStream.filter(...)。slotSharingGroup(“ name”);
因此,我根据我拥有的任务插槽的数量以及并行性定义了不同的组。
答案 1 :(得分:0)
我能够找到一种解决方法来平均分配插槽共享组。
从flink 1.9.2开始,甚至引入了任务分发功能,可以通过cluster.evenly-spread-out-slots: true
:FLINK-12122 Spread out tasks evenly across all available registered TaskManagers中的flink-conf.yaml
来打开它。我试图启用它,但是它没有用。经过深入研究后,我设法找到了开发人员的评论,其中指出该功能仅在独立模式下有效,因为它需要对资源进行初步的预分配-https://issues.apache.org/jira/browse/FLINK-12122?focusedCommentId=17013089&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-17013089":
此功能仅保证在计划时注册的所有TM上分散任务。因此,当您使用活动的纱线模式并提交第一份作业时,将不会注册任何TM。因此,Flink将分配第一个容器,将其填满,然后仅分配一个新容器。但是,如果您以独立模式启动Flink,或者在Yarn上完成第一项工作后,仍然注册了一些TM,那么下一项工作将散布开来。
因此,想法是从增加闲置容器超时设置开始a detached yarn session,首先提交一些短暂的假工作,这将简单地从YARN获取所需的资源并完成,然后立即启动主管道,它将分配给已经分配的容器,在这种情况下,cluster.evenly-spread-out-slots: true
可以解决问题,并平均分配所有插槽共享组。
因此,总而言之,执行以下操作以获取作业中均匀分布的插槽共享组:
resourcemanager.taskmanager-timeout
已增加,允许在为空闲任务管理器释放容器之前提交主要作业。我将其增加到1分钟,这足够了。yarn-session
并动态地向其提交作业。val env = StreamExecutionEnvironment.getExecutionEnvironment
val job = env
.fromElements(0)
.map { x =>
x * 2
}
.setParallelism(parallelismMax)
.print()
val jobResult = env.execute("Resources pre-allocation job")
println(jobResult)
print("Done. Starting main job!")