将值发送到输出主题后清除KTable条目

时间:2020-04-05 21:29:23

标签: apache-kafka apache-kafka-streams

我有一个数据库,用于存储每个网页的浏览量。通过使用名为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")

此拓扑有两个问题:

  1. 保存聚合的KTable在将输出消息生成到pageviews之后不会重置/清除,因此,仅将聚合值添加到DB表中,会得到错误的结果。如何实现发送给pageviews的每条消息不包含先前消息中已经发送的视图?

  2. 我希望每15分钟发送一次pageviews消息(默认速率大约是每30秒发送一次)。

我正在尝试为两者使用窗口,但是到目前为止,我还是失败了。

1 个答案:

答案 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");