我有一个使用Kafka Streams的Spring Boot应用程序。我有一个带有一些金融货币报价的KTable,其创建方式如下:
@Bean(name = "indicativeQuotes")
public KTable<String, Quote> quoteKTable(StreamsBuilder streamsBuilder) {
return streamsBuilder.table(quoteTopicName,
Materialized.<String,Quote,KeyValueStore<Bytes,byte[]>>as("quoteTable")
.withKeySerde(Serdes.String())
.withValueSerde(new JsonSerde<>(Quote.class)));
}
我@Autowire这个bean在另一个组件中,并使用以下代码对其进行测试:
@Autowired
private KTable<String, Quote> indicativeQuotes;
@PostConstruct
private void postConstruct() {
doPrint();
}
public void doPrint() {
ReadOnlyKeyValueStore<String, Quote> store = streamsBuilderFactoryBean.getKafkaStreams().store("quoteTable", QueryableStoreTypes.keyValueStore());
store.all().forEachRemaining(keyValue -> log.info("Key: " + keyValue.key + " Value: " + keyValue.value));
indicativeQuotes.foreach((k,v) -> log.info(k));}
该代码在通过store查询时会记录正确的值,但是在foreach()中什么也不输出,就像表是空的一样。我还尝试了print()和其他选项-所有输出均无任何异常。
我开始认为我不能像这样注入KTable bean,但是关于kafka流主题的Spring文档非常匮乏,我找不到很好的例子。任何帮助将不胜感激。
更新。
我的用例是我有一个计划的Quartz作业,该作业应在触发时将KTable的当前状态写入Kafka主题,如下所示:
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
log.info("Job was triggered by: {}", triggerKey.getName());
indicativeQuotes.filter((key, value) -> key.equals(triggerKey.getName()))
.mapValues(quoteToCourseFixedMapper)
.toStream()
.peek((instrument, course)-> log.info("Sending courses for instrument: {}, {}", instrument, course))
.to(quoteEventTopicName);
}
但是我认为该代码不起作用,因为它不是处理拓扑的一部分,并且我不能仅按需从Ktable获取数据。我有点困惑,当然,当事件触发时,我可以通过存储查询数据,但是对于这种用例,也许有更好的模式?基本上,我很感兴趣是否有可能将触发的工作事件纳入处理流程的一部分。
答案 0 :(得分:1)
如果只想将更新发布到另一个主题,请将KTable转换为KStream并使用to()函数。
KTable ktable = ...;
KStream ksteram = ktable.toStream();
kstream.to("topic", Produces.with(keySerde, valueSerde))
主题将包含该表的更改日志。
显然,由于某些与生命周期相关的概念,您不能只注入(@autowire
)KStream / KTable。您应该使与KafkaStreams相关的代码尽可能保持内联。
因此,在您的特定情况下,您想在某个“随机”时间内对表的当前状态执行某些操作,则必须查询存储(表)。因此,搜索kafka可以进行交互式查询。请记住,您需要从应用程序的所有实例中获取数据(如果您有多个实例,则可以这样做。或者您可以使用全局存储。这是一两天的搜索。