Flink Scala - 扩展WindowFunction

时间:2017-11-07 19:51:48

标签: scala apache-flink flink-streaming

我试图弄清楚如何编写我自己的WindowFunction但有问题,我无法弄清楚原因。我遇到的问题是apply函数,因为它不能将MyWindowFunction识别为有效输入,所以我无法编译。我流式传输的数据包含(timestamp,x,y),其中x和y为0和1用于测试。 extractTupleWithoutTs只返回一个元组(x,y)。我一直在使用简单的sum和reduce函数运行代码并且成功。感谢任何帮助:)使用Flink 1.3

进口:

import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks
import org.apache.flink.streaming.api.scala.function.WindowFunction
import org.apache.flink.streaming.api.watermark.Watermark
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector

其余代码:

val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val text = env.socketTextStream("localhost", 9999).assignTimestampsAndWatermarks(new TsExtractor)
val tuple = text.map( str => extractTupleWithoutTs(str))
val counts = tuple.keyBy(0).timeWindow(Time.seconds(5)).apply(new MyWindowFunction())
counts.print()
env.execute("Window Stream")

MyWindow函数,它基本上是从示例中复制粘贴的类型更改。

class MyWindowFunction extends WindowFunction[(Int, Int), Int, Int, TimeWindow] {
  def apply(key: Int, window: TimeWindow, input: Iterable[(Int, Int)], out: Collector[Int]): () = {
    var count = 0
    for (in <- input) {
      count = count + 1
    }
    out.collect(count)
  }
}

1 个答案:

答案 0 :(得分:3)

问题是WindowFunction的第三个类型参数,即密钥的类型。使用keyBy方法(keyBy(0))中的索引声明密钥。因此,在编译时无法确定密钥的类型。如果您将密钥声明为字符串,即keyBy("f0")

,则会出现同样的问题

有两种方法可以解决这个问题:

  1. 使用KeySelector中的keyBy功能提取密钥(类似keyBy(_._1))。 KeySelector函数的返回类型在编译时是已知的,这样您就可以使用带有WindowFunction键的正确键入的Int
  2. WindowFunction的第三个类型参数的类型更改为org.apache.flink.api.java.tuple.Tuple,即WindowFunction[(Int, Int), Int, org.apache.flink.api.java.tuple.Tuple, TimeWindow]TuplekeyBy提取的密钥的通用持有者。在您的情况下,它将是org.apache.flink.api.java.tuple.Tuple1。在WindowFunction.apply()中,您可以Tuple投放到Tuple1并通过Tuple1.f0访问关键字段。