我目前正在尝试在Spark应用程序中跟踪每分钟的请求,以便在另一个转换中使用它们。但是,在转换
中使用变量时,下面的代码永远不会产生除最初设置值0之外的其他值var rpm: Long = 0
val requestsPerMinute = stream.countByWindow(Seconds(60), Seconds(5)).foreachRDD(rdd => {
rdd.foreach(x => {
rpm = x
})
})
stream.foreachRDD { rdd =>
rdd.foreach(x => {
//do something including parameter rpm
})
}
我认为它必须对parellization做一些事情 - 我还尝试使用RDD或Broadcast而不是普通变量。但是这导致代码没有被执行。
在SparkStreaming中实现此目的的推荐方法是什么?
编辑: 传入的对象带有时间戳,如果这有助于任何事情。
答案 0 :(得分:2)
在Spark Streaming中,有两个执行级别:
有两个操作可以访问这两个级别:transform
和foreachRDD
。在这些操作中,我们可以访问驱动程序的上下文,并且我们可以使用RDD,我们可以使用它来对其应用计算。
在问题的具体情况下,要更新局部变量,必须在驱动程序的上下文中执行操作:
val requestsPerMinute = stream.countByWindow(Seconds(60), Seconds(5))
requestsPerMinute.foreachRDD{ rdd =>
val computedRPM = rdd.collect()(0) // this gets the data locally
rpm = computedRPM
}
在原案件中:
rdd.foreach(x => {
rpm = x
})
闭包:f(x): Long => Unit = rpm = x
被序列化并在集群上执行。副作用在远程上下文中应用,并在操作完成后丢失。在驱动程序级别,变量的值永远不会改变。
另外,请注意,使用副作用函数进行远程执行并不是一个好主意。