Apache flink 使用protobuf和flink

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

我正在使用flink从卡夫卡读取数据并将其转换为protobuf。我面临的问题是,当我运行java应用程序时,会出现以下错误。如果我将
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);
    }

  } 
}