处理多个PCollection输出时找不到编码器

时间:2018-01-24 19:34:31

标签: java google-cloud-platform google-cloud-dataflow apache-beam

我的管道的这部分应该接受输入,对其应用适当的元组标记,然后根据它接收的标记对输入进行进一步处理。

运行下面的代码时,主标签(tag1)中的PCollection正常工作。但是,附加标记(tag2,tag3)会在.apply()上抛出此错误:

  

线程“main”中的异常java.lang.IllegalStateException:无法为Assign Output.out1 [PCollection]返回默认编码器。更正以下根本原因之一:     没有手动指定编码器;你可以使用.setCoder()来完成。     从CoderRegistry推断编码器失败:无法为V提供编码器。

为什么tag2上会出现此错误,而tag1上却没有?注意,如果我将tag2作为主输出并将tag1 / tag3作为附加输出并对代码进行适当重新排序,则tag2处理成功,但tag1 / tag3将抛出错误。

主要管道:

PCollectionTuple pct  = outputPair.apply("Assign Output", ParDo.of( new output())
              .withOutputTags(output.tag1, TupleTagList.of(output.tag2).and(output.tag3)));

//Tag1 Output
PCollection<KV<String, outResultPair>> tagPair1 = pct.get(output.tag1)
        .apply("Process", ParDo.of( new ABCOutput()))

//Tag2 Output 
PCollection<KV<String, outResultPair>> tagPair2 = pct.get(output.tag2)
        .apply("Process", ParDo.of( new DEFOutput())) //Error Thrown here

支持课程:

    //ABCOutput Class 
    @DefaultCoder(AvroCoder.class)
    public class ABCOutput extends DoFn<KV<String, inResultPair>, KV<String, outResultPair>> {    
        @ProcessElement
        public void processElement(ProcessContext c) {
            KV<String, inResultPair> e = c.element();
            c.output( processInput(e) );
        }
    }

    //XYZOutput Class 
    @DefaultCoder(AvroCoder.class)
    public class XYZOutput extends DoFn<KV<String, inResultPair>, KV<String, outResultPair>> {    
        @ProcessElement
        public void processElement(ProcessContext c) {
            KV<String, inResultPair> e = c.element();
            c.output( processInput(e) );
        }
    }

    //Output Splitter
    @DefaultCoder(AvroCoder.class)
    public class output {
        private final static Logger LOG = LoggerFactory.getLogger(OutputHandler.class);

        final static TupleTag<KV<String,inResultPair>> tag1 = new TupleTag();
        final static TupleTag<KV<String,inResultPair>> tag2 = new TupleTag();
        final static TupleTag<KV<String,inResultPair>> tag3 = new TupleTag();
        @ProcessElement
        public void processElement(ProcessContext c) {
            KV<String, inResultPair> e = c.element();
            KV<String, outResultPair> out = process(e);

            switch(e.getValue().type){
                case 1:
                    c.output(tag1, out);
                break;
                case 2:
                    c.output(tag2, out);
                break;
                case 3:
                    c.output(tag3, out);
                break;
            }
            c.output();
        }

    }

1 个答案:

答案 0 :(得分:4)

你需要构建TupleTag的方式,它们的类型信息将由Java编译器保存,而目前你正在构建它们作为原始类型,所以Beam的编码器推断不知道是什么type是输出到此标记的元素。

变化:

 final static TupleTag<KV<String,inResultPair>> tag1 = new TupleTag();

为:

 final static TupleTag<KV<String,inResultPair>> tag1 =
     new TupleTag<KV<String, inResultPair>>() {};

{}对于保存类型信息至关重要。