我有一个数据库,用于存储每个网页的浏览量。通过使用名为pageviews
的Kafka主题来做到这一点,其中每条消息的页面名称为key
,而value
的视图数为自上一条消息以来的观看次数。
这是pageviews
主题中期望的消息样本:
综合浏览量主题:
key: "index", value: 349
key: "products", value: 67
key: "index", value: 15
key: "about", value: 11
...
pageviews
的使用者每次将以上values
都添加到PAGEVIEWS表中。
现在,我正在建立pageviews
主题的制作人。此应用程序的数据源是viewstream
主题,每个视图在其中创建一条消息,例如:
观看流主题:
key: "index", value: <timestamp>
key: "index", value: <timestamp>
key: "product", value: <timestamp>
...
在Kafka Stream应用程序上,我具有以下拓扑:
PageViewsStreamer:
builder.stream("viewstream")
.groupByKey()
.aggregate(...) // this builds a KTable with the sums of views per page
.toStream()
.to("pageviews")
此拓扑有两个问题:
保存聚合的KTable在将输出消息生成到pageviews
之后不会重置/清除,因此,仅将聚合值添加到DB表中,会得到错误的结果。如何实现发送给pageviews
的每条消息不包含先前消息中已经发送的视图?
我希望每15分钟发送一次pageviews
消息(默认速率大约是每30秒发送一次)。
我正在尝试为两者使用窗口,但是到目前为止,我还是失败了。
答案 0 :(得分:2)
您可以使用15分钟的滚动窗口来实现此行为,并在窗口时间过去之前抑制结果(请记住添加宽限时间以限制前一个窗口将接受的事件的延迟)。查看详细信息here。 我会做这样的事情:
builder.stream("viewstream")
.groupByKey()
//window by a 15-minute time windows, accept event late in 30 second, you can set grace time smaller
.windowedBy(TimeWindows.of(Duration.ofMinutes(15)).grace(Duration.ofSeconds(30)))
.aggregate(...) // this builds a KTable with the sums of views per page
.suppress(Suppressed.untilWindowCloses(Suppressed.BufferConfig.unbounded()))
.toStream()
//re-select key : from window to key
.selectKey((key, value) -> key.key())
.to("pageviews");