我正在向Kafka发送消息,如下所示:
private KafkaTemplate<String, MyMessage > kafkaTemplate;
public void sendMessage(MyMessage data) {
Message<MyMessage > message = MessageBuilder
.withPayload(data)
.setHeader(KafkaHeaders.TOPIC,topic)
.setHeader(KafkaHeaders.MESSAGE_KEY,data.getKey())
.build();
kafkaTemplate.send(message);
我对MyMessage有自己的自定义解串器,键是一个简单的String
我正在尝试按以下方式处理消息:
@StreamListener
public void process(@Input("input") KStream<String,MyMessage> myStream){
final Serde<String> stringSerde = Serdes.String();
final MyMessageSerde myMessageSerde = new MyMessageSerde();
myStream
.groupBy((key,value)-> value.getObjectKey(), Serialized.with(stringSerde,myMessageSerde))
.aggregate(ArrayList::new,
(newKey,val,agg) -> {
agg.add(val);
return agg;
},
Materialized.<String, ArrayList<MyMessage>, KeyValueStore<Bytes, byte[]>>as("object-keys")
.withKeySerde(stringSerde)
.withValueSerde(new ArrayListSerde(myMessageSerde)));
...
interface MyStreamProcessor {
@Input("input")
KStream<?, ?> input();
}
这失败,发生反序列化错误,调试后我看到原因是消息的内容类型标头设置为application / json,因此它正尝试将消息反序列化为JSON。如何设置内容类型标头,如何覆盖它?我不是以JSON的形式发送消息,而是像常规的Kafka消息那样以byte []的形式发送消息,因此我希望使用自定义的de / serializer
甚至更陌生的是,如果我将其更改为KTable,则可以正常工作。
@StreamListener
public void process(@Input("input") KTable<String,MyMessage> myTable){
final Serde<String> stringSerde = Serdes.String();
final MyMessageSerde myMessageSerde = new MyMessageSerde();
KStream<String,MyMessage> myStream = myTable.toStream();
myStream
.groupBy((key,value)-> value.getObjectKey(), Serialized.with(stringSerde,myMessageSerde))
.aggregate(ArrayList::new,
(newKey,val,agg) -> {
agg.add(val);
return agg;
},
Materialized.<String, ArrayList<MyMessage>, KeyValueStore<Bytes, byte[]>>as("object-keys")
.withKeySerde(stringSerde)
.withValueSerde(new ArrayListSerde(myMessageSerde)));
...
interface MyStreamProcessor {
@Input("input")
KTable<?, ?> input();
}
为什么使用KTable可以正确反序列化消息? KStream和KTable之间的行为有什么区别?
答案 0 :(得分:0)
答案 1 :(得分:0)
我通过执行以下操作使它起作用:
在我的application.yml文件中设置输入内容类型标头,如下所示:
spring.cloud.stream.bindings.input.content-type: application/mymessage
创建一个CustomMessageConverter,它扩展AbstractMessageConverter以便从字节[]转换为MyMessage。它还定义了新的MimeType
public MyMappingConverter() {
super(new MimeType("application", "mymessage"));
}
@Bean
@StreamMessageConverter
public MessageConverter myMessageConverter() {
return new MyMessageConverter();
}
我仍然不知道为什么我必须对KStream而不是对KTable进行所有这些操作,如果有人可以解释说,将不胜感激。