我最近在Flink的新版本中研究ProcessWindowFunction
。它说ProcessWindowFunction
支持全局状态和窗口状态。我使用Scala API试一试。到目前为止,我可以让全球国家工作,但我没有任何运气可以用于窗口状态。我正在做的是处理系统日志并计算主机名和严重性级别键入的日志数。我想计算两个相邻窗口之间的日志计数差异。这是我的代码实现ProcessWindowFunction
。
class LogProcWindowFunction extends ProcessWindowFunction[LogEvent, LogEvent, Tuple, TimeWindow] {
// Create a descriptor for ValueState
private final val valueStateWindowDesc = new ValueStateDescriptor[Long](
"windowCounters",
createTypeInformation[Long])
private final val reducingStateGlobalDesc = new ReducingStateDescriptor[Long](
"globalCounters",
new SumReduceFunction(),
createTypeInformation[Long])
override def process(key: Tuple, context: Context, elements: Iterable[LogEvent], out: Collector[LogEvent]): Unit = {
// Initialize the per-key and per-window ValueState
val valueWindowState = context.windowState.getState(valueStateWindowDesc)
val reducingGlobalState = context.globalState.getReducingState(reducingStateGlobalDesc)
val latestWindowCount = valueWindowState.value()
println(s"lastWindowCount: $latestWindowCount ......")
val latestGlobalCount = if (reducingGlobalState.get() == null) 0L else reducingGlobalState.get()
// Compute the necessary statistics and determine if we should launch an alarm
val eventCount = elements.size
// Update the related state
valueWindowState.update(eventCount.toLong)
reducingGlobalState.add(eventCount.toLong)
for (elem <- elements) {
out.collect(elem)
}
}
}
我总是从窗口状态获取0
值,而不是之前应该更新的计数。几天来我一直在努力解决这个问题。有人可以帮我解决一下吗?感谢。
答案 0 :(得分:1)
每个窗口状态的范围是单个窗口实例。对于上面的process
方法,每次调用它时,新窗口都在范围内,因此latestWindowCount始终为零。
对于一个只会触发一次的普通香草窗口,每窗口状态是无用的。只有当窗口以某种方式进行多次点火(例如,后期点火)时,才能充分利用每窗口状态。如果您试图记住从一个窗口到下一个窗口的内容,那么您可以使用全局窗口状态来执行此操作。
有关使用每窗口状态记住要在晚期点火中使用的数据的示例,请参阅Flink advanced window training中的幻灯片13-19。