Scala foreachPartitionAsync抛出无法在已停止的SparkContext上调用方法
我有两个不同数据的文件。我试图在2个不同的RDD中读取它们,然后将它们转换为数据帧并插入到hive中。我能够完成这个普通的代码,但是spark处理了一个又一个RDD计算。所以第二个在等待第一个过去,尽管我在集群中有足够的资源。我了解到RDDs计算可以使用异步方法并行化。所以我正在尝试foreachPartitionAsync。但它抛出了我无法进一步调试的错误。示例代码:Scala foreachPartitionAsync抛出无法在已停止的SparkContext上调用方法,scala,asynchronous,apache-spark,future,Scala,Asynchronous,Apache Spark,Future,我有两个不同数据的文件。我试图在2个不同的RDD中读取它们,然后将它们转换为数据帧并插入到hive中。我能够完成这个普通的代码,但是spark处理了一个又一个RDD计算。所以第二个在等待第一个过去,尽管我在集群中有足够的资源。我了解到RDDs计算可以使用异步方法并行化。所以我正在尝试foreachPartitionAsync。但它抛出了我无法进一步调试的错误。示例代码: object asynccode { def main(args: Array[String]) = { val
object asynccode {
def main(args: Array[String]) = {
val conf = new SparkConf()
.setAppName("Parser")
val sc = new SparkContext(conf)
val hiveContext = new HiveContext(sc)
import hiveContext.implicits._
val ercs = sc.wholeTextFiles("hdfs://x.x.x.x:8020/file1.txt")
val test = ercs.map { k =>
var rc = method1(k._2, k._1).toSeq
rc
}
.flatMap(identity)
.foreachPartitionAsync { f =>
f.toSeq.toDF()
.write.insertInto("dbname.tablename1")
}
val ercs2 = sc.wholeTextFiles("hdfs://x.x.x.x:8020/file2.txt")
val test2 = ercs2.map { k =>
var rs = method2(k._2, k._1)
rs
}
.flatMap(identity)
.foreachPartitionAsync(f => f.toSeq.toDF()
.write.insertInto("dbname.tablename2")
)
sc.stop()
}
def method1 = ???
def method2 = ???
}
但它会抛出下面的错误消息。如果我从代码中删除foreachPartitionAsync,它可以正常工作。不确定我在foreachPartitionAsync方面做错了什么
任务序列化失败:java.lang.IllegalStateException:无法对已停止的SparkContext调用方法
更新:
谢谢你的建议。我更新了它如下。但现在它什么也没做。Spark web UI,我看不到任何阶段被触发(它是空的)。我的表也没有更新。但这项工作是毫无错误地完成的
val ercs = sc.wholeTextFiles("hdfs://x.x.x.x:8020/file1.txt")
val test = ercs.map { k =>
var rc = method1(k._2, k._1).toSeq
rc
}
.flatMap(identity)
toDF()
val f1 = Future(test.write.insertInto("dbname.tablename1"))
}
val ercs2 = sc.wholeTextFiles("hdfs://x.x.x.x:8020/file2.txt")
val test2 = ercs2.map { k =>
var rs = method2(k._2, k._1)
rs
}
.flatMap(identity)
toSeq.toDF()
val f2 = Future(test2.write.insertInto("dbname.tablename2"))
)
Future.sequence(Seq(f1,f2)).onComplete(_ => sc.stop)
我错过了什么吗?您停止
SparkContext
,而不必等待未来行动的完成。您应该等待操作完成并停止上下文响应:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Success, Failure}
val f1: Future[Unit] = sc.range(1, 200).foreachAsync(_ => Thread.sleep(10))
val f2: Future[Unit] = sc.range(1, 200).foreachAsync(_ => Thread.sleep(10))
Future.sequence(Seq(f1, f2)).onComplete {
case Success(_) => sc.stop
case Failure(e) =>
e.printStackTrace // or some other appropriate actions
sc.stop
}
也就是说,即使我们忽略异步操作,您的代码也是无效的。不能在操作或转换中使用分布式数据结构:
如果您想要异步写入操作,请直接使用Futures
:
val df1: Dataframe = ???
val df2: Dataframe = ???
val f1: Future[Unit] = Future(df1.write.insertInto("dbname.tablename1"))
val f2: Future[Unit] = Future(df2.write.insertInto("dbname.tablename2"))
并等待上述操作完成
val df1: Dataframe = ???
val df2: Dataframe = ???
val f1: Future[Unit] = Future(df1.write.insertInto("dbname.tablename1"))
val f2: Future[Unit] = Future(df2.write.insertInto("dbname.tablename2"))