是否可以使用dataflow将数据从pubsub传输到数据存储区?

时间:2018-08-20 07:57:29

标签: google-cloud-platform google-cloud-datastore google-cloud-dataflow google-cloud-pubsub

我尝试使用数据流将数据从pubsub流到数据存储。

参考: https://github.com/GoogleCloudPlatform/DataflowTemplates/tree/master/src/main/java/com/google/cloud/teleport/templates

我尝试构建模板,但是它根本不起作用。 因此,我认为这是不可能的。

怎么样? 请给我一些建议。

1 个答案:

答案 0 :(得分:1)

您可能偶然发现了该特定模板中的错误。其中有两个独立的问题,第一个是在此SO问题How to use google provided template [pubsub to Datastore]?中回答的一个问题,该问题指向丢失的CourseTable.courseName,第二个问题是数据存储区的编写者在以下情况下实际上使用了errorTag它将实体写入数据存储。

如果使用GroupByKey选项运行maven compile命令,它将显示错误消息-e。为什么这样做呢?它与消息是从PubSub流传输而不是分批处理(这是我们期望的)有关。这意味着没有有限的项目集正在流入,而没有止境的项目流。为了对此进行处理,我们需要将其限制为可以由诸如GroupByKey cannot be applied to non-bounded PCollection in the GlobalWindow without a trigger. Use a Window.into or Window.triggering transform prior to GroupByKey之类的聚合函数考虑的项目流窗口。 GroupByKey类有助于将实体写入数据存储区,实际上检查我们是否尝试多次写入同一密钥,并通过使用DatastoreConverters函数来完成。

简单的解决方案,只需为其提供一个流式处理窗口即可,这是在管道中添加了第三个GroupByKey,可将流式窗口组合在一起,并允许您在此处使用数据存储写入器:

.apply(...)

现在还有其他方法,并且可能做得更好,但这将使您的模板得以编译和工作。此示例显示了1秒的FixedWindow,还有其他选项可以执行此操作,请查看该文档Google DataFlow - Windowing

使用以下代码编译模板:

import org.apache.beam.sdk.transforms.windowing.FixedWindows;
import org.apache.beam.sdk.transforms.windowing.Window;
import org.apache.beam.sdk.values.TupleTag;
import org.joda.time.Duration;

... 

  public static void main(String[] args) {
    PubsubToDatastoreOptions options = PipelineOptionsFactory.fromArgs(args)
        .withValidation()
        .as(PubsubToDatastoreOptions.class);

    Pipeline pipeline = Pipeline.create(options);
    TupleTag<String> errorTag = new TupleTag<String>("errors") {};

    pipeline
        .apply(PubsubIO.readStrings()
            .fromTopic(options.getPubsubReadTopic()))
        .apply(TransformTextViaJavascript.newBuilder()
            .setFileSystemPath(options.getJavascriptTextTransformGcsPath())
            .setFunctionName(options.getJavascriptTextTransformFunctionName())
            .build())
        .apply(Window.<String>into(FixedWindows.of(Duration.standardSeconds(1))))
        .apply(WriteJsonEntities.newBuilder()
            .setProjectId(options.getDatastoreWriteProjectId())
            .setErrorTag(errorTag)
            .build());

    pipeline.run();
  }

然后使用以下命令启动作业:

mvn compile exec:java -Dexec.mainClass=com.google.cloud.teleport.templates.PubsubToDatastore -Dexec.cleanupDaemonThreads=false -Dexec.args=" \
--project=[YOUR_PROJECTID_HERE] \
--stagingLocation=gs://[YOUR_BUCKET_HERE]/staging \
--tempLocation=gs://[YOUR_BUCKET_HERE]/temp \
--templateLocation=gs://[YOUR_BUCKET_HERE]/templates/PubsubToDatastore.json \
--runner=DataflowRunner"

现在,如果您在那里查看,您应该会看到您的作业正在GCP控制台中运行:

DataFlow job running in GCP console

请注意,此特定的解决方案和选择的窗口将导致PubSub消息最终在数据存储区中延迟一秒钟。缩短窗口可能会有所帮助,但要获得更高的吞吐量,您需要的管道与此处显示的管道不同。