Java 使用反应式api将卡夫卡主题读到最后
我们使用压缩卡夫卡主题来存储状态更改,在重新启动或重新平衡期间,需要通过将主题读到最后并获取每个键的最后一个条目来恢复状态 对于非反应性消费者,我们可以Java 使用反应式api将卡夫卡主题读到最后,java,apache-kafka,project-reactor,Java,Apache Kafka,Project Reactor,我们使用压缩卡夫卡主题来存储状态更改,在重新启动或重新平衡期间,需要通过将主题读到最后并获取每个键的最后一个条目来恢复状态 对于非反应性消费者,我们可以 // get assigned partitions Set<TopicPartition> assignment = consumer.assignment(); // get "end" offset for every partition Map<TopicPartition, Long> endOffsets =
// get assigned partitions
Set<TopicPartition> assignment = consumer.assignment();
// get "end" offset for every partition
Map<TopicPartition, Long> endOffsets = consumer.endOffsets(assignment);
// poll data until "end" is reached for every partition
...
给定一个
卡夫卡接收器
,您应该能够执行以下操作:
receiver.receive()
.zipWith(receiver.doOnConsumer(Consumer::assignment)
.flatMap(a -> receiver.doOnConsumer(c -> c.endOffsets(a)))
.filter(m -> !m.isEmpty())
.single()
.retry()
.cache()
.repeat())
.groupBy(t -> t.getT1().partition())
.flatMap(f -> f.filter(t -> t.getT1().offset()+1 == (long) t.getT2().get(new TopicPartition(topic, f.key()))))
.map(t -> t.getT1())
关于我为什么这样做的一些注释:
- 这将为您提供一个
,即每个分区中的最后一个Flux
ReceiverRecord
- 通常我会说,不要为接收者创建单独的变量,只需将其全部内联——但使用
是不可能做到这一点的,因为doonsumer()
不受反应式assignment()
的直接支持KafkaReceiver
- 我通常尽量避免使用
从本质上合并zipWith()
和重复缓存的Flux
,而倾向于使用Mono
。但是,在这种情况下,我认为这是行不通的,因为您需要在flatMapMany()
返回除空集以外的任何内容之前主动轮询主题assignment()
concatMap
和内偏移Mono的缓存,使用doOnConsumer
获取消费者位置,而不是记录偏移量以检查结束,并takeUntil
以完成发布。我将发布我的代码
receiver.receive()
.zipWith(receiver.doOnConsumer(Consumer::assignment)
.flatMap(a -> receiver.doOnConsumer(c -> c.endOffsets(a)))
.filter(m -> !m.isEmpty())
.single()
.retry()
.cache()
.repeat())
.groupBy(t -> t.getT1().partition())
.flatMap(f -> f.filter(t -> t.getT1().offset()+1 == (long) t.getT2().get(new TopicPartition(topic, f.key()))))
.map(t -> t.getT1())