如何在kafka流中关闭窗口时发送关于主题的记录

时间:2018-02-28 10:51:35

标签: apache-kafka-streams windowed

所以我实际上已经花了几天时间。我正在使用4个主题的记录。我需要在TimedWindow上聚合记录。当时间到了,我想将批准的消息或未批准的消息发送到接收器主题。这可能与kafka流有关吗?

即使窗口仍处于打开状态,它似乎也会将每个记录都放到新主题中,而这真的不是我想要的。

以下是简单的代码:

 builder.stream(getTopicList(), Consumed.with(Serdes.ByteArray(), 
 Serdes.ByteArray()))
.flatMap(new ExceptionSafeKeyValueMapper<String, 
 FooTriggerMessage>("", Serdes.String(),
       fooTriggerSerde))
 .filter((key, value) -> value.getTriggerEventId() != null)
 .groupBy((key, value) -> value.getTriggerEventId().toString(),
       Serialized.with(Serdes.String(), fooTriggerSerde))

.windowedBy(TimeWindows.of(TimeUnit.SECONDS.toMillis(30))
.advanceBy(TimeUnit.SECONDS.toMillis(30)))

.aggregate(() -> new BarApprovalMessage(), /* initializer */
       (key, value, aggValue) -> getApproval(key, value, aggValue),/*adder*/
       Materialized
               .<String, BarApprovalMessage, WindowStore<Bytes, byte[]>>as(
                       storeName) /* state store name */
               .withValueSerde(barApprovalSerde))
.toStream().to(appProperties.getBarApprovalEngineOutgoing(), 
Produced.with(windowedSerde, barApprovalSerde));

截至目前,每条记录都被下载到outgoingTopic,我只希望它在窗口关闭时发送一条消息,可以这么说。

这可能吗?

3 个答案:

答案 0 :(得分:4)

我回答了我自己的问题,如果有人需要答案的话。在转换阶段,我使用上下文来创建调度程序。该调度程序有三个参数。标点的间隔时间,使用时间(挂钟或流时间)和供应商(满足时间时要调用的方法)。我使用了挂钟时间并为每个唯一的窗口键启动了一个新的调度程序。我在KeyValue存储中添加每条消息并返回null。然后,在每30秒调用一次的方法中,我检查窗口是否已关闭,并迭代密钥库中的消息,聚合并使用context.forward和context.commit。中提琴!在30秒窗口中收到4条消息,产生一条消息。

答案 1 :(得分:1)

答案 2 :(得分:0)

我遇到了这个问题,但是我解决了这个问题,在固定窗口之后并使用抑制的API添加了grace(0)

public void process(KStream<SensorKeyDTO, SensorDataDTO> stream) {

        buildAggregateMetricsBySensor(stream)
                .to(outputTopic, Produced.with(String(), new SensorAggregateMetricsSerde()));

    }

private KStream<String, SensorAggregateMetricsDTO> buildAggregateMetricsBySensor(KStream<SensorKeyDTO, SensorDataDTO> stream) {
        return stream
                .map((key, val) -> new KeyValue<>(val.getId(), val))
                .groupByKey(Grouped.with(String(), new SensorDataSerde()))
                .windowedBy(TimeWindows.of(Duration.ofMinutes(WINDOW_SIZE_IN_MINUTES)).grace(Duration.ofMillis(0)))
                .aggregate(SensorAggregateMetricsDTO::new,
                        (String k, SensorDataDTO v, SensorAggregateMetricsDTO va) -> aggregateData(v, va),
                        buildWindowPersistentStore())
                .suppress(Suppressed.untilWindowCloses(unbounded()))
                .toStream()
                .map((key, value) -> KeyValue.pair(key.key(), value));
    }


    private Materialized<String, SensorAggregateMetricsDTO, WindowStore<Bytes, byte[]>> buildWindowPersistentStore() {
        return Materialized
                .<String, SensorAggregateMetricsDTO, WindowStore<Bytes, byte[]>>as(WINDOW_STORE_NAME)
                .withKeySerde(String())
                .withValueSerde(new SensorAggregateMetricsSerde());
    }

在这里您可以看到结果

enter image description here