Apache flink 什么';s KeyedStream#timeWindow#进程中键和窗口实例之间的关系

Apache flink 什么';s KeyedStream#timeWindow#进程中键和窗口实例之间的关系,apache-flink,Apache Flink,对于KeyedStream#timeWindow#process,我想知道一个窗口实例是否只包含相同的键,而不同的键将使用不同的窗口实例 从以下应用程序的输出中,我看到一个窗口实例将只包含相同的键,而不同的键将使用不同的窗口 但我想问一下并确认一下,谢谢 import org.apache.flink.streaming.api.functions.source.{RichParallelSourceFunction, SourceFunction} import scala.util.Ran

对于
KeyedStream#timeWindow#process
,我想知道一个窗口实例是否只包含相同的键,而不同的键将使用不同的窗口实例

从以下应用程序的输出中,我看到一个窗口实例将只包含相同的键,而不同的键将使用不同的窗口

但我想问一下并确认一下,谢谢

import org.apache.flink.streaming.api.functions.source.{RichParallelSourceFunction, SourceFunction}

import scala.util.Random

class KeyByAndWindowAndProcessTestSource extends RichParallelSourceFunction[Int] {
  override def run(ctx: SourceFunction.SourceContext[Int]): Unit = {

    while (true) {
      val i = new Random().nextInt(30)
      ctx.collect(i)
      ctx.collect(i)
      ctx.collect(i)

      Thread.sleep(1000)
    }

  }

  override def cancel(): Unit = {

  }
}
申请表格如下:

import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.scala.function.ProcessWindowFunction
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector
import org.apache.flink.api.scala._


object KeyByAndWindowTest {

  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    env.getCheckpointConfig.setCheckpointInterval(10 * 1000)
    env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime)
    val ds: DataStream[Int] = env.addSource(new KeyByAndWindowAndProcessTestSource)
    val ds2 = ds.keyBy(i => i).timeWindow(Time.seconds(4)).process(new MyProcessFunction())
    ds2.print()
    env.execute()
  }

}


class MyProcessFunction extends ProcessWindowFunction[Int, String, Int, TimeWindow] {


  override def process(
                        key: Int,
                        ctx: Context,
                        vals: Iterable[Int],
                        out: Collector[String]): Unit = {

    println(new java.util.Date())

    println(s"key=${key}, vals = ${vals.mkString(",")}, hashCode=${System.identityHashCode(ctx.window)}")
  }
}
输出为:

Sat Sep 14 13:08:24 CST 2019
key=26, vals = 26,26,26, hashCode=838523304
Sat Sep 14 13:08:24 CST 2019
key=28, vals = 28,28,28, hashCode=472721641
Sat Sep 14 13:08:24 CST 2019
key=18, vals = 18,18,18,18,18,18, hashCode=1668151956
原始答复:

我希望我能正确回答你的问题

ProcessWindowFunction#进程
将为每个窗口和键调用一次(或多次,具体取决于窗口的触发器)。在内部,窗口和键组成了一个复合分区键

就Java对象实例而言,
ProcessWindowFunction
的一个实例将处理许多键。具体来说,许多ProcessWindowFunction都具有一定的并行度

后续行动:

所以我没有弄对:)

对于由
WindowOperator
处理的每条记录,将创建一个新的
Window
对象,该对象具有正确的记录开始/结束时间

这意味着每次调用
ProcessWindowFunction#process
都会传递一个新的
Window
对象

必须了解,Flink中的
窗口
是一个非常轻的对象,它只是用作整个键的附加部分(命名空间)。它不包含任何数据和/或逻辑


我可以问一下这个问题的背景吗

实际上,对于ProcessingTimeWindow,会为每个元素创建一个新的window对象

以下是TumblingProcessingTimeWindows#assignWindows的源代码:

    public Collection<TimeWindow> assignWindows(Object element, long timestamp, WindowAssignerContext context) {
        final long now = context.getCurrentProcessingTime();
        long start = TimeWindow.getWindowStartWithOffset(now, offset, size);
        return Collections.singletonList(new TimeWindow(start, start + size));
    }
公共集合分配窗口(对象元素、长时间戳、WindowAssignerContext上下文){
final long now=context.getCurrentProcessingTime();
long start=TimeWindow.GetWindowsStartWithOffset(现在,偏移量,大小);
返回集合.singletonList(新的时间窗口(开始,开始+大小));
}
因此,
System.identityHashCode
将始终为不同的键返回一个唯一的哈希代码,而您的测试代码不会证明任何东西


在引擎盖下,元素按
elementKey+assignedWindow
的键进行分组,因此我认为可以说“一个窗口实例将只包含相同的键,不同的键将使用不同的窗口实例”。

谢谢@snntrable。我的问题是关于一个键将有一个窗口实例。例如,我有两个键,a、b,两个键落在同一个时间窗口中(例如,08:00-08:15),但窗口实例不同(它们是不同的窗口对象)。谢谢@snntrable。这里没有什么特别的背景,我只是好奇它的内部工作情况。如果我对它的内部工作有更好的了解,我将能够正确而自信地编写代码。。