我们有一个Spark流应用程序,它可以提取数据 @ 10,000 / sec ...我们在DStream上使用foreachRDD操作(因为除非在DStream上找到输出操作,否则spark不会执行)
因此我们必须使用这样的foreachRDD输出操作,它需要 3小时 ...来编写单一数据(10,000)慢
CodeSnippet 1:
requestsWithState.foreachRDD { rdd =>
rdd.foreach {
case (topicsTableName, hashKeyTemp, attributeValueUpdate) => {
val client = new AmazonDynamoDBClient()
val request = new UpdateItemRequest(topicsTableName, hashKeyTemp, attributeValueUpdate)
try client.updateItem(request)
catch {
case se: Exception => println("Error executing updateItem!\nTable ", se)
}
}
case null =>
}
}
}
所以我认为foreachRDD中的代码可能是问题,所以请注意它需要花多少时间.... 令我惊讶的是......即使在foreachRDD中使用了nocode它仍然运行了3个小时
CodeSnippet 2:
requestsWithState.foreachRDD {
rdd => rdd.foreach {
// No code here still takes a lot of time ( there used to be code but removed it to see if it's any faster without code) //
}
}
请告诉我们,如果我们遗漏了任何内容或其他方法来执行此操作,因为我理解没有DStream上的输出操作火花流应用程序将无法运行..此时我无法使用其他输出操作...
注意:要隔离问题并确保发电机代码没有问题...我用空循环运行.....看起来就像foreachRDD在迭代一个巨大的记录集时自己很慢在@ 10,000 /秒...而不是发电机代码为空的foreachRDD和发电机代码花了相同的时间......
ScreenShot显示执行的所有阶段和 foreachRDD 所花费的时间,即使它是循环播放且内部没有代码
foreachRDD空循环所花费的时间
foreachRDD空循环的9个工作节点中大型运行任务的任务分配...
答案 0 :(得分:1)
我知道已经晚了,但是如果您想听听,我有一些猜测可能会为您提供一些见识。
不是rdd.foreach
中的代码花费很长时间,而是rdd.foreach
之前的代码,它生成rdd。
转换是惰性的,直到您使用结果,spark才会对其进行计算。
当代码在rdd.foreach
中运行时,spark进行计算并生成数据行。rdd.foreach循环中的代码仅处理结果。
您可以通过注释rdd.foreach
requestsWithState.foreachRDD {
//rdd => rdd.foreach {
// No code here still takes a lot of time ( there used to be code but removed it to //see if it's any faster without code)
//}
}
我想它将非常快,因为不会进行任何计算。 或者您可以将转换更改为非常简单的转换,它也会很快。 它不能解决您的问题,但是如果我说对了,它将帮助您找到问题所在。
答案 1 :(得分:0)
您是否尝试过如下所示的无循环操作?
//requestsWithState.foreachRDD {
//rdd => rdd.foreach {
// No code here //
// }
//}
foreachRDD
花费的时间而不是其中的代码。请注意,它是foreach
而不是for
。无论内部是否有代码,它都会运行n
次。
有效测试可用于性能测试:
https://tech.ovoenergy.com/spark-streaming-in-production-testing/