我正在尝试使用Kafka 0.8.1构建POC。我使用自己的java类作为Kafka消息,它有一堆String数据类型。我不能使用默认的序列化程序类或Kafka库附带的String serializer类。我想我需要编写自己的序列化程序并将其提供给生产者属性。 如果您知道在Kafka中编写示例自定义序列化程序(在java中),请分享。 非常感谢,非常感谢。
答案 0 :(得分:41)
编写自定义序列化程序所需的东西是:
Encoder
VerifiableProperties
构造函数toBytes(...)
方法,确保返回字节数组ProducerConfig
正如您在问题中所述,Kafka提供了一种为生产者声明特定序列化器的方法。序列化程序类在ProducerConfig
实例中设置,该实例用于构造所需的Producer
类。
如果您关注Kafka's Producer Example,则会通过ProducerConfig
对象构建Properties
。构建属性文件时,请务必包括:
props.put("serializer.class", "path.to.your.CustomSerializer");
使用类的路径,您希望Kafka在将消息附加到日志之前用它来序列化消息。
编写Kafka可以正确解释的自定义序列化程序需要实现Kafka提供的Encoder[T]
scala类。 Implementing traits in java is weird,但以下方法适用于在我的项目中序列化JSON:
public class JsonEncoder implements Encoder<Object> {
private static final Logger logger = Logger.getLogger(JsonEncoder.class);
// instantiating ObjectMapper is expensive. In real life, prefer injecting the value.
private static final ObjectMapper objectMapper = new ObjectMapper();
public JsonEncoder(VerifiableProperties verifiableProperties) {
/* This constructor must be present for successful compile. */
}
@Override
public byte[] toBytes(Object object) {
try {
return objectMapper.writeValueAsString(object).getBytes();
} catch (JsonProcessingException e) {
logger.error(String.format("Json processing failed for object: %s", object.getClass().getName()), e);
}
return "".getBytes();
}
}
您的问题听起来好像您正在使用一个对象(让我们称之为CustomMessage
)来附加到您的日志中的所有邮件。如果是这种情况,您的序列化程序可能看起来更像这样:
package com.project.serializer;
public class CustomMessageEncoder implements Encoder<CustomMessage> {
public CustomMessageEncoder(VerifiableProperties verifiableProperties) {
/* This constructor must be present for successful compile. */
}
@Override
public byte[] toBytes(CustomMessage customMessage) {
return customMessage.toBytes();
}
}
这将使您的属性配置看起来像这样:
props.put("serializer.class", "path.to.your.CustomSerializer");
答案 1 :(得分:12)
您需要实现编码和解码器
public class JsonEncoder implements Encoder<Object> {
private static final Logger LOGGER = Logger.getLogger(JsonEncoder.class);
public JsonEncoder(VerifiableProperties verifiableProperties) {
/* This constructor must be present for successful compile. */
}
@Override
public byte[] toBytes(Object object) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(object).getBytes();
} catch (JsonProcessingException e) {
LOGGER.error(String.format("Json processing failed for object: %s", object.getClass().getName()), e);
}
return "".getBytes();
}
}
解码器代码
public class JsonDecoder implements Decoder<Object> {
private static final Logger LOGGER = Logger.getLogger(JsonEncoder.class);
public JsonDecoder(VerifiableProperties verifiableProperties) {
/* This constructor must be present for successful compile. */
}
@Override
public Object fromBytes(byte[] bytes) {
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.readValue(bytes, Map.class);
} catch (IOException e) {
LOGGER.error(String.format("Json processing failed for object: %s", bytes.toString()), e);
}
return null;
}
}
pom条目
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.3</version>
</dependency>
在Kafka属性中设置默认编码器
properties.put("serializer.class","kafka.serializer.DefaultEncoder");
作者和读者代码如下
byte[] bytes = encoder.toBytes(map);
KeyedMessage<String, byte[]> message =new KeyedMessage<String, byte[]>(this.topic, bytes);
JsonDecoder decoder = new JsonDecoder(null);
Map map = (Map) decoder.fromBytes(it.next().message());
答案 2 :(得分:0)
因此,我不能使用默认的序列化程序类或Kafka库随附的StringSerializer。
可以。
例如,使用Jackson或Gson;将您的实例转换为JSON字符串or (preferrably) binary bytearray,然后使用内置的Kafka序列化程序之一。
推荐
为您的班级使用Avro或Protobuf序列化器的Confluent版本以及Schema Registry。
如果您将类写到ByteArraySerializer
,也可以只使用ObjectOutputStream
(但是,由于不支持跨语言,因此不建议这样做)。