我已经使用带有生成的Java源代码的Avro模式文件编写了Kafka Avro Deserializer。要求是不要使用POJO。如何使以下代码不使用POJO和通用模式转换。
import java.util.Arrays;
import java.util.Map;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.Decoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Deserializer;
import com.example.org.model.Person;
public class AvroDeserializer implements Deserializer<GenericRecord> {
@Override
public void close() {
}
@Override
public void configure(Map<String, ?> configs, boolean isKey) {
}
@Override
public GenericRecord deserialize(String topic, byte[] data) {
try {
GenericRecord result = null;
if (data != null) {
DatumReader<Person> reader = new SpecificDatumReader<>
(Person.getSchema());
Decoder decoder = DecoderFactory.get().binaryDecoder(data, null);
result = (GenericRecord) reader.read(null, decoder);
}
return result;
} catch (Exception ex) {
throw new SerializationException(
"Can't deserialize data '" + Arrays.toString(data) + "' from topic '" + topic + "'", ex);
}
}
}
如何使此代码不使用POJO。
答案 0 :(得分:0)
如果您在Serilizer中使用POJO类,那么您将存储模式以及数据,这些数据将在解析消息时变慢,并且还会在存储级别占用额外的空间。
您必须在Serilizer
和DeSerilizer
中进行更改。
要解决此问题,请使用Schema Registry。
架构注册表的基本思想是,在将数据读写到主题时,生产者/消费者将引用avro架构。
我们不想像您暗示的那样为每个数据编写模式-通常,模式大于您的数据!那样会浪费时间在每次读取时进行解析,也浪费了资源(网络,磁盘,CPU)
我建议您通过以下链接获取代码以及对该主题的详细描述。
答案 1 :(得分:0)
有几种方法可以做到这一点。您可以将其添加到构造函数中:
protected final Class<T> targetType;
public AvroDeserializer(Class<T> targetType) {
this.targetType = targetType;
}
并使用targetType反序列化:
SpecificDatumReader<GenericRecord> datumReader =
new SpecificDatumReader<>(targetType.newInstance().getSchema());
然后,从客户端使用反序列化器:
AvroEmbeddedDeserializer<Test> avroEmbeddedDeserializer = new AvroEmbeddedDeserializer<>(Test.class);
final KafkaConsumer<String, Test> consumer = new KafkaConsumer<>(props, stringDeserializer, avroEmbeddedDeserializer);
请注意,使用这种方法时,您不能使用反序列化属性来配置您的使用者,因为它使用了空的构造函数。