全天计算来自kafka主题的消息

时间:2018-05-17 15:29:19

标签: scala apache-kafka

我想计算来自kakfa主题的消息。

例如我有这个案例类:

case class Message(timestamp: LocalDateTime)

我收到了这堂课的留言,我想知道我在1小时内收到多少留言。假设在本主题中排序消息(时间戳对应于消息在主题中输入的时间)。

我想创建一个这样的案例类:

case class Counter(datetime: LocalDateTime, count: Int)

假设我在第一个小时内有100条消息,然后是150条消息:

Counter("2018-05-17 00:00:00", 100)
Counter("2018-05-17 00:01:00", 150)

关于如何做到这一点的任何想法?有关信息,我不能/不想使用kafka-streams。

谢谢!

编辑:

我的来源是一个kafka主题,我想与Consumer API一起使用。我的接收器是一个postgresql表。

2 个答案:

答案 0 :(得分:1)

您想要的解决方案通常在流处理术语中称为 windowing ,大多数流处理库都将此作为一项功能。软件工厂的a good writeup比较了Spark Streaming,Flink,Kafka Streams和Akka Streams。

您可以尝试自己实现它,但上面提到的库都经过测试,并且具有简单,可读的API。如果您不想使用Kafka Streams,那么其中一条评论中提到的Akka Streams KafkaAlpakka project的一部分)就值得考虑。

答案 1 :(得分:0)

我找到了Flink的解决方案。

我在Flink中阅读了一些关于时间窗口的文档,这篇page讨论了主题中提升的时间戳(这是我的情况)。

所以这是一个解决方案:

  val inputStream: DataStream[Message] = env.addSource(kafkaConsumer)
  val timedStream: DataStream[Message] = inputStream
    .assignAscendingTimestamps(_.timestamp)
  val timeWindow = timedStream.timeWindowAll(Time.minutes(1)).sum(1)

计算1分钟内翻滚窗口内的所有元素。

要获得更具体的解决方案并到达Counter("2018-05-17 00:00:00", 100),我们必须延长AllWindowFunction

  class CustomWindowFunction extends AllWindowFunction[Message, Counter, TimeWindow] {
  def apply(window: TimeWindow, input: Iterable[Message], out: Collector[Counter]): Unit = {
    out.collect(
      Counter(
        new LocalDateTime(window.getStart),
        input.size
      )
    )
  }
}

然后将其应用于我们的timeStream:

  val inputStream: DataStream[MyClass] = env.addSource(kafkaConsumer)
  val timedStream: DataStream[MyClass] = inputStream
    .assignAscendingTimestamps(_.timestamp)
  val timeWindow = timedStream.timeWindowAll(Time.minutes(1)).apply(new CustomWindowFunction())

如果在我们的输入主题中我们有Message类,那么我们最后会获得Counter类。

这是更好的"我现在找到的解决方案。