繁体   English   中英

整小时统计来自kafka主题的消息

[英]Count messages from kafka topic all hour

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

例如,我有这个案例类:

case class Message(timestamp: LocalDateTime)

我收到此类信息,我想计算一下我在一小时内收到多少信息。 假设消息在该主题中排序(时间戳对应于消息在主题中输入的时间)。

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

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。

谢谢!

编辑:

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

所需的解决方案通常在流处理术语中称为窗口化 ,大多数流处理库都将此作为功能。 Software Mill有一个很好的文章 ,比较了Spark Streaming,Flink,Kafka Streams和Akka Streams。

您可以尝试自己实现它,但是上面提到的库都经过了严格的测试,并具有简单易读的API。 如果您不想使用Kafka Streams,那么其中一项评论( Alpakka项目的一部分)中提到的Akka Streams Kafka值得考虑。

我想出了Flink解决方案。

我阅读了Flink中有关时间窗口的一些文档,并且此页面讨论了有关主题中的升序时间戳(这是我的情况)。

所以这里是一个解决方案:

  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类。

这是我现在发现的“更好”的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM