Flink + Kafka 0.10:如何使用Kafka消息时间戳作为字段创建表?

时间:2017-10-28 07:14:03

标签: apache-flink flink-streaming

我想将FlinkKafkaConsumer010生成的消息的时间戳提取为数据流中的值。

我知道AssignerWithPeriodicWatermarks类,但这似乎只是通过DataStream API提取时间聚合的时间戳。

我想在Table中提供Kafka消息时间戳,以后可以使用SQL。

编辑:试过这个:

  val consumer = new FlinkKafkaConsumer010("test", new SimpleStringSchema, properties)
  consumer.setStartFromEarliest()

  val env = StreamExecutionEnvironment.getExecutionEnvironment
  val tenv = TableEnvironment.getTableEnvironment(env)

  env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

  class KafkaAssigner[T] extends AssignerWithPeriodicWatermarks[T] {
    var maxTs = 0L
    override def extractTimestamp(element: T, previousElementTimestamp: Long): Long = {
      maxTs = Math.max(maxTs, previousElementTimestamp)
      previousElementTimestamp
    }
    override def getCurrentWatermark: Watermark = new Watermark(maxTs - 1L)
  }

  val stream = env
    .addSource(consumer)
    .assignTimestampsAndWatermarks(new KafkaAssigner[String])
    .flatMap(_.split("\\W+"))

  val tbl = tenv.fromDataStream(stream, 'w, 'ts.rowtime)

它编译,但抛出:

Exception in thread "main" org.apache.flink.table.api.TableException: Field reference expression requested.
    at org.apache.flink.table.api.TableEnvironment$$anonfun$1.apply(TableEnvironment.scala:630)
    at org.apache.flink.table.api.TableEnvironment$$anonfun$1.apply(TableEnvironment.scala:624)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241)
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
    at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
    at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241)
    at scala.collection.mutable.ArrayOps$ofRef.flatMap(ArrayOps.scala:186)
    at org.apache.flink.table.api.TableEnvironment.getFieldInfo(TableEnvironment.scala:624)
    at org.apache.flink.table.api.StreamTableEnvironment.registerDataStreamInternal(StreamTableEnvironment.scala:398)
    at org.apache.flink.table.api.scala.StreamTableEnvironment.fromDataStream(StreamTableEnvironment.scala:85)

在上面代码的最后一行。

EDIT2 :感谢@ fabian-hueske指出我的解决方法。 https://github.com/andrey-savov/flink-kafka

的完整代码

1 个答案:

答案 0 :(得分:0)

如果配置了时间特征EventTime,Flink的Kafka 0.10使用者会自动将Kafka消息的时间戳设置为生成记录的事件时间戳(参见docs)。

在您将Kafka主题摄取到DataStream时,如果时间戳(仍然不可见)和分配的水印,您可以使用Table方法将其转换为StreamTableEnvironment.fromDataStream(stream, fieldExpr*)fieldExpr*参数是描述生成的表的模式的表达式列表。您可以使用表达式mytime.rowtime添加保存流的记录时间戳的字段,其中mytime是新字段的名称,rowtime表示从记录中提取值时间戳。请查看docs for details

注意:正如@bfair指出的那样,原子类型DataStream的转换(例如DataStream[String])失败,Flink 1.3.2和早期版本。该错误已报告为FLINK-7939,并将在下一版本中修复。