Apache kafka streams 如何在卡夫卡流中关闭窗口时发送主题记录
所以我已经为此苦苦挣扎了几天,事实上。我正在使用4个主题的记录。我需要在一段时间内汇总这些记录。时间到了,我想向接收主题发送已批准或未批准的消息。这可能与卡夫卡流有关吗 它似乎把每一张唱片都放在了新的主题上,即使窗口还开着,但这并不是我想要的 下面是简单的代码:Apache kafka streams 如何在卡夫卡流中关闭窗口时发送主题记录,apache-kafka-streams,windowed,Apache Kafka Streams,Windowed,所以我已经为此苦苦挣扎了几天,事实上。我正在使用4个主题的记录。我需要在一段时间内汇总这些记录。时间到了,我想向接收主题发送已批准或未批准的消息。这可能与卡夫卡流有关吗 它似乎把每一张唱片都放在了新的主题上,即使窗口还开着,但这并不是我想要的 下面是简单的代码: builder.stream(getTopicList(), Consumed.with(Serdes.ByteArray(), Serdes.ByteArray())) .flatMap(new ExceptionSafeKey
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));
builder.stream(getTopicList(),consumered.with(Serdes.ByteArray(),s),
Serdes.ByteArray())
.flatMap(新的例外情况SafeKeyValueMapper(“),Serdes.String(),
fooTriggerSerde)
.filter((键,值)->value.getTriggerEventId()!=null)
.groupBy((键,值)->value.getTriggerEventId().toString(),
序列化的.with(Serdes.String(),fooTriggerSerde))
.windowedBy(TimeWindows.of(TimeUnit.SECONDS.toMillis(30))
.advanceBy(时间单位为秒。托米利斯(30)))
.aggregate(()->new BarApprovalMessage(),/*初始值设定项*/
(key,value,aggValue)->getApproval(key,value,aggValue),/*加法器*/
具体化
.作为(
storeName)/*状态存储名称*/
.带ValueSerde(barApprovalSerde))
.toStream().to(appProperties.getBarApprovalEngineOutgoing(),
制作。使用(windowedSerde、Baraprovalsorde));
到目前为止,每一条记录都被放到了主题上,可以说,我只希望它在窗口关闭时发送一条消息
这可能吗?如果其他人需要答案,我会回答自己的问题。在转换阶段,我使用上下文创建了一个调度程序。此计划程序接受三个参数。要加标点的时间间隔、要使用的时间(挂钟或流时间)和供应商(满足时间要求时调用的方法)。我使用了挂钟时间,并为每个唯一的窗口键启动了一个新的调度程序。我将每条消息添加到KeyValue存储中并返回null。然后,在每30秒调用一次的方法中,我检查窗口是否关闭,并迭代密钥库中的消息,聚合并使用context.forward和context.commit。中提琴!在30秒内收到4条消息,生成一条消息 您可以使用抑制功能 卡夫卡官方指南:
我遇到了这个问题,但我解决了这个问题,在固定窗口之后添加了grace(0)并使用了抑制API
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());
}
公共作废流程(KStream流){
buildAggregateMetricsBySensor(流)
.to(outputTopic,producted.with(String(),new SensorAggregateMetricsSerde());
}
专用KStream buildAggregateMetricsBySensor(KStream stream){
回流
.map((key,val)->新的KeyValue(val.getId(),val))
.groupByKey(分组为.with(String(),new SensorDataSerde())
.windowedBy(TimeWindows.of(持续时间分钟)(窗口大小以分钟为单位)).grace(持续时间百万分(0)))
.聚合(SensorAggregateMetricsDTO::新建,
(字符串k,传感器数据到v,传感器聚合技术到va)->聚合数据(v,va),
buildWindowPersistentStore())
.suppress(supprested.untilwindowclose(unbounded()))
.toStream()
.map((key,value)->KeyValue.pair(key.key(),value));
}
私有物化buildWindowPersistentStore(){
回报物化
.as(窗口\商店\名称)
.withKeySerde(字符串())
.带ValueSerde(新传感器聚合矩阵顺序());
}
在这里你可以看到结果
是否有可能重复使用此示例代码?这将非常有帮助,我正在为会话窗口开发一个类似的用例。我写了一篇关于它的博客文章。它是用瑞典语写的,但我猜代码部分无论如何都是有意义的。如果没有,我可以试着把它贴出来!非常感谢!大部分都是有意义的,因为我的用例有点不同,所以工作缓慢(不能安排固定的等待,因为会话可能没有完成)。然而,在您的示例中,“调度器”来自哪里?我不确定类型是什么,也没有看到它在任何地方被声明。事实上,对于sentIdsList来说,这是一个相同的问题,我想你应该把它传递给已经发送的内容的映射。这是一个状态存储,还是来自不同的东西?调度程序持有可取消项。我在变压器里申报。使用context.schedule在给定间隔处加标点。Sentidslist是一个全局变量。但是我认为你不需要关于那个的信息:)酷!然后我的黑客不再需要:)标记这是解决方案!这对活动时间来说不是仍然有效吗。如果我们想用挂钟时间来抑制呢?