Google cloud dataflow 在运行时读取多个文件(数据流模板)

Google cloud dataflow 在运行时读取多个文件(数据流模板),google-cloud-dataflow,apache-beam,dataflow,apache-beam-io,Google Cloud Dataflow,Apache Beam,Dataflow,Apache Beam Io,我正在尝试构建一个数据流模板 目标是读取ValueProvider,它将告诉我要读取哪些文件。 然后,对于每个文件,我需要使用对象读取和丰富数据。 我试过这个: p.apply(Create.of(options.getScheduleBatch())) .apply(ParDo.of(StringScheduleBatchToFileReceivedFn.of())) .apply(ParDo.of(new DoFn<Fil

我正在尝试构建一个数据流模板

目标是读取ValueProvider,它将告诉我要读取哪些文件。 然后,对于每个文件,我需要使用对象读取和丰富数据。 我试过这个:

        p.apply(Create.of(options.getScheduleBatch()))
            .apply(ParDo.of(StringScheduleBatchToFileReceivedFn.of()))
            .apply(ParDo.of(new DoFn<FileReceived, PCollection<EventRow>>() {
                @ProcessElement
                public void process(ProcessContext c) {
                    FileReceived fileReceived = c.element();
                    Broker broker = configuration.getBroker(fileReceived.getBrokerId());
                    PCollection<EventRow> eventRows = p
                            .apply(TextIO.read().from(fileReceived.getUri()))
                            .apply(ParDo.of(StringToEventRowFn.of(broker, fileReceived, options.getJobName())));
                    c.output(eventRows);
                }
            }));
p.apply(创建.of(options.getScheduleBatch()))
.apply(ParDo.of(StringScheduleBatchToFileReceivedFn.of()))
.适用(新DoFn()的第{
@过程元素
公共作废流程(ProcessContext c){
FileReceived FileReceived=c.element();
Broker Broker=configuration.getBroker(fileReceived.getBrokerId());
PCollection eventRows=p
.apply(TextIO.read().from(fileReceived.getUri()))
.apply(ParDo.of(StringToEventRowFn.of(broker,fileReceived,options.getJobName()));
c、 输出(事件行);
}
}));
但我有以下错误:

从CoderRegistry推断编码器失败:无法为org.apache.beam.sdk.values.PCollection提供编码器

我想找到一个比自己使用gcs客户端读取文件更好的方法

你有什么建议吗


向问题问好:

您正试图发出一个
PCollection
,作为
ParDo
的输出。这不管用

详细信息:

PCollection
是一个抽象,表示一个潜在的无限元素集合。将转换应用于
PCollection
将提供另一个
PCollection
。可以应用的转换之一是
ParDo
ParDos
进行元素转换。当应用你所表达的
ParDo
时—“使用这个
PCollection
并通过应用该
ParDo
转换其中的所有元素来制作另一个”

使处理有效的因素之一是能够并行执行所有内容,例如,通过针对不同的元素在每个执行节点上运行相同的
ParDo
,在多个执行节点(例如虚拟机/机器)上一次性转换大量元素。您无法明确控制任何特定转换是在同一个执行节点上发生还是在另一个执行节点上发生,如何优化转换是底层系统设计的一部分。但要实现这一点,您必须能够在执行节点之间传递元素,并将它们持久化以进行聚合。Beam通过要求您为元素实现
编码器来支持这一点。编码器是一种序列化机制,允许Beam将元素(由java对象表示)转换为字节数组,然后可以将其传递到下一个转换(可能发生在另一台机器上)或存储器。例如,Beam需要能够对从
ParDo
输出的元素进行编码。Beam知道如何序列化某些类型,但它无法自动推断所有类型,您必须为无法推断的类型提供编码器

您的示例如下所示:取一些
PCollection
,通过对每个元素应用
ParDo
将其转换为另一个
PCollection
,然后
ParDo
将每个输入元素转换为
PCollection
。这意味着一旦元素被
ParDo
处理,就必须对其进行编码并将其传递给下一个转换。这里的问题是-如何编码(可能是无边界的)
PCollection
并将其传递给下一个转换或将其持久化以进行聚合

Beam目前不支持这一点,因此您需要选择另一种方法

在您的特定情况下,我不确定是否可以在Beam-out-of-the-box中简单地使用文件名流并将其转换为子管道来处理文件中的行

解决方法:

我能想到的绕过这一限制的几种方法:

  • 如果文件名具有已知模式,则可以在
    TextIO
    中指定该模式,并且它可以在新文件到达时读取它们

  • 如果它们没有已知的模式,您可以编写另一个管道来重命名文件名,使它们具有公共名称模式,然后在另一个管道中使用
    TextIO
    中的模式

  • 如果可行(例如,文件适合内存),您可能可以使用纯java
    File
    API读取文件内容,将其拆分为行,并在单个
    ParDo
    中发出这些行。然后,您可以在下面的
    ParDo
    中应用相同的
    StringToEventRowFn


希望这有帮助

您好,谢谢您的回答,我已经改变了方法。我使用FileIO.matchAll+FileIO.readMatches,然后对于读取的每一行,我返回一个KV,键是文件名和一行的值。在站点上,我建立了一个PCollection视图作为地图,我将使用KV的键获取值。