Apache flink 使用protobuf和flink
我正在使用flink从卡夫卡读取数据并将其转换为protobuf。我面临的问题是,当我运行java应用程序时,会出现以下错误。如果我将Apache flink 使用protobuf和flink,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我正在使用flink从卡夫卡读取数据并将其转换为protobuf。我面临的问题是,当我运行java应用程序时,会出现以下错误。如果我将unknownFields变量名修改为其他名称,它会起作用,但很难对所有protobuf类进行更改 我还试图在读取卡夫卡时直接反序列化,但我不确定getProducedType()方法返回的TypeInformation应该是什么 public static class ProtoDeserializer implements Deserializatio
unknownFields
变量名修改为其他名称,它会起作用,但很难对所有protobuf类进行更改
我还试图在读取卡夫卡时直接反序列化,但我不确定getProducedType()
方法返回的TypeInformation
应该是什么
public static class ProtoDeserializer implements DeserializationSchema{
@Override
public TypeInformation getProducedType() {
// TODO Auto-generated method stub
return PrimitiveArrayTypeInfo.BYTE_PRIMITIVE_ARRAY_TYPE_INFO;
}
谢谢你的帮助。谢谢
java.lang.RuntimeException:受字段保护的com.google.protobuf.UnknownFieldSet com.google.protobuf.GeneratedMessage.unknownFields已包含在类com.google.protobuf.GeneratedMessage的层次结构中。请通过类层次结构使用唯一的字段名
位于org.apache.flink.api.java.typeutils.TypeExtractor.getAllDeclaredFields(TypeExtractor.java:1594)
位于org.apache.flink.api.java.typeutils.TypeExtractor.analyzePojo(TypeExtractor.java:1515)
位于org.apache.flink.api.java.typeutils.TypeExtractor.privateGetForClass(TypeExtractor.java:1412)
位于org.apache.flink.api.java.typeutils.TypeExtractor.privateGetForClass(TypeExtractor.java:1319)
位于org.apache.flink.api.java.typeutils.TypeExtractor.createTypeInfoWithTypeHierarchy(TypeExtractor.java:609)
位于org.apache.flink.api.java.typeutils.TypeExtractor.privateCreateTypeInfo(TypeExtractor.java:437)
位于org.apache.flink.api.java.typeutils.TypeExtractor.getUnaryOperatorReturnType(TypeExtractor.java:306)
位于org.apache.flink.api.java.typeutils.TypeExtractor.getFlatMapReturnTypes(TypeExtractor.java:133)
位于org.apache.flink.streaming.api.datastream.datastream.flatMap(datastream.java:529)
代码:
FlinkKafkaConsumer09-kafkaConsumer=new FlinkKafkaConsumer09(“testArr”,new ByteDes(),p);
数据流输入=env.addSource(kafkaConsumer);
DataStream protoData=input.map(新的RichMapFunction(){
@凌驾
公共地址映射(字节[]值)引发异常{
PBAddress addr=PBAddress.parseFrom(值);
返回地址;
}
});
试试这个:
public class ProtoDeserializer implements DeserializationSchema<PBAddress> {
@Override
public TypeInformation<PBAddress> getProducedType() {
return TypeInformation.of(PBAddress.class);
}
公共类ProtoDeserializer实现反序列化模式{
@凌驾
公共类型信息getProducedType(){
返回TypeInformation.of(PBAddress.class);
}
也许您应该尝试以下方法:
env.getConfig().registerTypeWithKryoSerializer(PBAddress. class,ProtobufSerializer.class);
或
env.getConfig().registerTypeWithKryoSerializer(PBAddress.class,PBAddressSerializer.class);
公共类PBAddressSerializer扩展了序列化程序{
最终私有映射hashMap=新hashMap();
受保护的方法getParse(类cls)抛出NoSuchMethodException{
Method=hashMap.get(cls);
if(方法==null){
method=cls.getMethod(“parseFrom”,新类[]{byte[].Class});
put(cls,method);
}
返回法;
}
@凌驾
公共无效写入(Kryo-Kryo、输出、消息){
字节[]ser=message.toByteArray();
output.writeInt(序列长度,true);
输出写字节(ser);
}
@凌驾
公共消息读取(Kryo Kryo,输入,类pbClass){
试一试{
int size=input.readInt(true);
字节[]barr=新字节[大小];
输入读取(barr);
return(Message)getParse(pbClass).invoke(null,barr);
}捕获(例外e){
抛出新的RuntimeException(“无法创建”+pbClass,e);
}
}
}
是JIRA记录单,跟踪使用可演化模式实现对Protobuf类型的一流支持的问题。您会看到,很久以前有一个pull请求,它还没有被合并。我相信问题是,在Protobuf以前被使用的情况下,没有支持处理状态迁移通过在Kryo注册它
同时,有状态函数项目(statefun是一个运行在Flink之上的新API)完全基于Protobuf,它包括对将Protobuf与Flink一起使用的支持:。(该包的入口点是ProtobufTypeInformation.java。)我建议探索这个包(它不包含任何特定于statefun的内容);但是,它也与从Kryo迁移无关。您解决了这个问题吗?我找到的唯一解决办法是直接在flink kafka consumer上反序列化数据,方法是提供适当的反序列化程序而不是映射函数。
env.getConfig().registerTypeWithKryoSerializer(PBAddress. class,ProtobufSerializer.class);
env.getConfig().registerTypeWithKryoSerializer(PBAddress. class,PBAddressSerializer.class);
public class PBAddressSerializer extends Serializer<Message> {
final private Map<Class,Method> hashMap = new HashMap<Class, Method>();
protected Method getParse(Class cls) throws NoSuchMethodException {
Method method = hashMap.get(cls);
if (method == null) {
method = cls.getMethod("parseFrom",new Class[]{byte[].class});
hashMap.put(cls,method);
}
return method;
}
@Override
public void write(Kryo kryo, Output output, Message message) {
byte[] ser = message.toByteArray();
output.writeInt(ser.length,true);
output.writeBytes(ser);
}
@Override
public Message read(Kryo kryo, Input input, Class<Message> pbClass) {
try {
int size = input.readInt(true);
byte[] barr = new byte[size];
input.read(barr);
return (Message) getParse(pbClass).invoke(null,barr);
} catch (Exception e) {
throw new RuntimeException("Could not create " + pbClass, e);
}
}
}