我以下列方式提交多个火花工作 -
someCollection.foreach(m => {
..some code
sparkSubmitClass.run(m.name)
.. some code
})
其中sparkSubmitClass.run()方法基本上使用具有$ SPARK_HOME / bin / spark-submit和其他相关参数的shell脚本。
问题在于此代码一次性提交所有火花作业。我想要实现的是 - 提交一份工作,然后只有在较早的工作完成时提交另一份工作。这是因为someCollection是有序的,下一个作业依赖于前一个作业创建的数据。
sparkSubmitClass.run()位于以下行 -
def run(appName: String)(implicit executionContext: ExecutionContext) = {
val command = s"sparkJob.sh $appName"
val processBuilder = Process(command)
val pio = new ProcessIO(_ => (),
stdout => {
scala.io.Source.fromInputStream(stdout)
.getLines.foreach(str => log.info(s"spark-submit: Application
Name=$appName stdout='${str.replace("'", "\\'")}'"))
},
stderr => {
val lines = scala.io.Source.fromInputStream(stderr).getLines().toBuffer
lines.foreach(str => log.info(s"spark-submit: Application Name=$appName
stderr='${str.replace("'", "\\'")}'"))
lines.flatMap(parseLineForApplicationUrl).headOption.foreach(appId =>
appId)
})
val process = processBuilder.run(pio)
val exitVal = process.exitValue() //returns 0 as soon as application is
submitted
}
sparkJob.sh基本上是 -
MAIN_CLASS="com.SomeClassHavingRDDAndHiveOperations"
APPNAME=$1
JAVA_OPTS="-XX:MaxDirectMemorySize=$WORKER_DIRECT_MEM_SIZE -
XX:+HeapDumpOnOutOfMemoryError -Djava.net.preferIPv4Stack=true"
SPARK_HOME="/usr/lib/spark"
cmd='$SPARK_HOME/bin/spark-submit --class $MAIN_CLASS
--name ${APPNAME}
--conf "spark.yarn.submit.waitAppCompletion=false"
--conf "spark.io.compression.codec=snappy"
--conf "spark.kryo.unsafe=true"
--conf "spark.kryoserializer.buffer.max=1024m"
--conf "spark.serializer=org.apache.spark.serializer.KryoSerializer"
--driver-java-options "-XX:MaxMetaspaceSize=$WORKER_PERM_SIZE $JAVA_OPTS"
$appdir/SomeJar.jar $APPNAME'
eval $cmd
有关如何构建此类订购的任何想法?
答案 0 :(得分:1)
而不是编写bash scripts
并调用每个作业并浪费io /读写阶段,而不是在代码中根据需要循环作业。
这里有一些提示供你遵循:
首先,您必须确保拥有interface
,然后对要按顺序处理的每个interface
实施class
,以便您可以使用method
开始每个工作。 (在此示例中,方法为进程,界面为 JobInterface )
然后,您需要使用所需的顺序将所有class-names-with-package
写入一个文件中。假设该文件为orderedJobs
(您不需要提及扩展名)
package1.Class1
package1.Class2
package2.Class3
....
读取并解析该文件。我假设它在resouces文件夹中,你可以过滤你不想要的行
val classCall = Source.fromInputStream(getClass.getResourceAsStream(<locationOforderedJobs>)).getLines().filter(!_.startsWith("#"))
为每个类循环foreach
并调用定义的公共方法(process
)
classCall.foreach(job => {
processJob(job).process(<you can pass arguments>)
}
processJob
是funtion
,您可以在其中实例化每个类
def processJob(name: String): JobInterface = {
val action = Class.forName("<package path from source root>"+className).newInstance()
action.asInstanceOf[JobInterface]
}
通过这种方式,您可以减少io /读写时间浪费,通过在内存中存储其他作业的有用数据来提高火花处理效率,缩短处理时间等等...... <登记/> 我希望它有所帮助