我想计算来自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表。
答案 0 :(得分:1)
您想要的解决方案通常在流处理术语中称为 windowing ,大多数流处理库都将此作为一项功能。软件工厂的a good writeup比较了Spark Streaming,Flink,Kafka Streams和Akka Streams。
您可以尝试自己实现它,但上面提到的库都经过测试,并且具有简单,可读的API。如果您不想使用Kafka Streams,那么其中一条评论中提到的Akka Streams Kafka(Alpakka 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
类。
这是更好的"我现在找到的解决方案。