在Spark Streaming中跟踪每分钟的请求

时间:2017-08-04 21:10:10

标签: scala apache-spark spark-streaming

我目前正在尝试在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中实现此目的的推荐方法是什么?

编辑: 传入的对象带有时间戳,如果这有助于任何事情。

1 个答案:

答案 0 :(得分:2)

在Spark Streaming中,有两个执行级别:

  • 在驱动程序中执行的操作计划,
  • 在群集中执行的RDD上的分布式计算

有两个操作可以访问这两个级别:transformforeachRDD。在这些操作中,我们可以访问驱动程序的上下文,并且我们可以使用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被序列化并在集群上执行。副作用在远程上下文中应用,并在操作完成后丢失。在驱动程序级别,变量的值永远不会改变。

另外,请注意,使用副作用函数进行远程执行并不是一个好主意。