我正在运行基于mapWithState DStream函数的Spark Streaming应用程序。应用程序根据记录中的会话ID字段将输入记录转换为会话。
会话只是具有相同ID的所有记录。然后我在会话级别执行一些分析以找到异常分数。
我无法稳定我的应用程序,因为少数会话在每个批次时间内变得越来越长(超过1小时)。我的理解是单个会话(键 - 值对)总是由spark中的单个核心处理。我想知道我是否错了,如果有解决方案来缓解此问题并使流应用程序稳定。
我在Yarn上使用Hadoop 2.7.2和Spark 1.6.1。更改批处理时间,阻塞间隔,分区号,执行程序号和执行程序资源并没有解决问题,因为单个任务使应用程序始终窒息。但是,过滤那些超长会话解决了这个问题。
下面是我正在使用的代码updateState函数:
val updateState = (batchTime: Time, key: String, value: Option[scala.collection.Map[String,Any]], state: State[Seq[scala.collection.Map[String,Any]]]) => {
val session = Seq(value.getOrElse(scala.collection.Map[String,Any]())) ++ state.getOption.getOrElse(Seq[scala.collection.Map[String,Any]]())
if (state.isTimingOut()) {
Option(null)
} else {
state.update(session)
Some((key,value,session))
}
}
和mapWithStae调用:
def updateStreamingState(inputDstream:DStream[scala.collection.Map[String,Any]]): DStream[(String,Option[scala.collection.Map[String,Any]], Seq[scala.collection.Map[String,Any]])] ={//MapWithStateDStream[(String,Option[scala.collection.Map[String,Any]], Seq[scala.collection.Map[String,Any]])] = {
val spec = StateSpec.function(updateState)
spec.timeout(Duration(sessionTimeout))
spec.numPartitions(192)
inputDstream.map(ds => (ds(sessionizationFieldName).toString, ds)).mapWithState(spec)
}
最后,我正在应用一个特色计算会话foreach DStream,定义如下:
def computeSessionFeatures(sessionId:String,sessionRecords: Seq[scala.collection.Map[String,Any]]): Session = {
val features = Functions.getSessionFeatures(sessionizationFeatures,recordFeatures,sessionRecords)
val resultSession = new Session(sessionId,sessionizationFieldName,sessionRecords)
resultSession.features = features
return resultSession
}