我正在使用ReplyingKafkaTemplate
向Kafka发送消息,并且正在与kafka_correlationId
发送消息。但是,当它到达我的@KafkaListener
方法并将其转发给回复主题时,标头会丢失。
如何保存kafka标头?
这是我的方法签名:
@KafkaListener(topics = "input")
@SendTo("reply")
public List<CustomOutput> consume(List<CustomInput> inputs) {
... /* some processing */
return outputs;
}
我已经创建了ProducerInterceptor
,所以我可以看到正在从ReplyingKafkaTemplate
以及从@SendTo
批注发送的标题。因此,另一个奇怪的事情是ReplyingKafkaTemplate
没有在邮件中添加记录的kafka_replyTopic
标头。
ReplyingKafkaTemplate
的配置方式如下:
@Bean
public KafkaMessageListenerContainer<Object, Object> replyContainer(ConsumerFactory<Object, Object> cf) {
ContainerProperties containerProperties = new ContainerProperties(requestReplyTopic);
return new KafkaMessageListenerContainer<>(cf, containerProperties);
}
@Bean
public ReplyingKafkaTemplate<Object, Object, Object> replyingKafkaTemplate(ProducerFactory<Object, Object> pf, KafkaMessageListenerContainer<Object, Object> container) {
return new ReplyingKafkaTemplate<>(pf, container);
}
我不确定这是否相关,但是我也添加了 Spring Cloud Sleuth 作为依赖项,并且在发送消息时,span / trace标头就存在了,但是转发消息时会生成新消息。
答案 0 :(得分:1)
默认情况下,请求消息中的任意标头不会复制到回复消息中,而只会复制到kafka_correlationId
。
从2.2版开始,您可以配置ReplyHeadersConfigurer
,调用该ReplyHeadersConfigurer
以确定应复制哪些标头。
从2.2版开始,您可以将
Message<?>
添加到侦听器容器工厂。请咨询以确定您要在回复消息中设置的标头。
编辑
顺便说一句,在2.2中,如果没有标题,RKT会自动设置replyTo。
使用2.1.x可以完成此操作,但这有点复杂,您必须自己做一些工作。关键是接收和回复@KafkaListener(id = "so55622224", topics = "so55622224")
@SendTo("dummy.we.use.the.header.instead")
public Message<?> listen(Message<String> in) {
System.out.println(in);
Headers nativeHeaders = in.getHeaders().get(KafkaHeaders.NATIVE_HEADERS, Headers.class);
byte[] replyTo = nativeHeaders.lastHeader(KafkaHeaders.REPLY_TOPIC).value();
byte[] correlation = nativeHeaders.lastHeader(KafkaHeaders.CORRELATION_ID).value();
return MessageBuilder.withPayload(in.getPayload().toUpperCase())
.setHeader("myHeader", nativeHeaders.lastHeader("myHeader").value())
.setHeader(KafkaHeaders.CORRELATION_ID, correlation)
.setHeader(KafkaHeaders.TOPIC, replyTo)
.build();
}
// This is used to send the reply - needs a header mapper
@Bean
public KafkaTemplate<?, ?> kafkaTemplate(ProducerFactory<Object, Object> kafkaProducerFactory) {
KafkaTemplate<Object, Object> kafkaTemplate = new KafkaTemplate<>(kafkaProducerFactory);
MessagingMessageConverter messageConverter = new MessagingMessageConverter();
messageConverter.setHeaderMapper(new SimpleKafkaHeaderMapper("*")); // map all byte[] headers
kafkaTemplate.setMessageConverter(messageConverter);
return kafkaTemplate;
}
@Bean
public ApplicationRunner runner(ReplyingKafkaTemplate<String, String, String> template) {
return args -> {
Headers headers = new RecordHeaders();
headers.add(new RecordHeader("myHeader", "myHeaderValue".getBytes()));
headers.add(new RecordHeader(KafkaHeaders.REPLY_TOPIC, "so55622224.replies".getBytes())); // automatic in 2.2
ProducerRecord<String, String> record = new ProducerRecord<>("so55622224", null, null, "foo", headers);
RequestReplyFuture<String, String, String> future = template.sendAndReceive(record);
ConsumerRecord<String, String> reply = future.get();
System.out.println("Reply: " + reply.value() + " myHeader="
+ new String(reply.headers().lastHeader("myHeader").value()));
};
}
...
frozenset