使用ParDo的processElement来使用REST API

时间:2016-02-24 22:13:12

标签: java firebase google-cloud-dataflow

虽然我正在快速修复CSV到Firebase上传,但我做的不是编写自定义接收器。这是对代码的过度简化:

public static void main(String[] args) throws Exception {

    Options options = PipelineOptionsFactory.as(Options.class);
    Pipeline p = Pipeline.create(options);

    PCollection<String> CsvData = p.apply(TextIO.Read.from("/my_file.csv"));
    CsvData.apply(ParDo.named("Firebase").of(new DoFn<String, Void>() {
          @Override
          public void processElement(ProcessContext c) {
              Firebase fb = new Firebase("https://MYAPP.firebaseio.com/");
              fb.child("someId").setValue(c.element.getValue());
          }
        });

}

有效。这是否应该在Cloud Dataflow上使用REST API?

1 个答案:

答案 0 :(得分:5)

是的,这应该有效,假设您可以使用以下警告:如果出现故障,可以多次复制或重试捆绑包,即可以在同一个元素上调用您的processElement调用时间,可能同时发生。

即使Dataflow会对结果进行重复数据删除(即只有一个成功调用的项目通过c.output()发出,最终会产生PCollection),重复删除副作用(例如进行外部API调用)是你的代码的责任。

自定义接收器API仅强调这些问题并提供一种处理它们的“模式”(通过提供具有唯一ID的bundle并提供钩子来提交成功结果 - 例如,基于文件的接收器将使每个bundle写入到唯一命名的临时文件,并且提交挂钩会将成功完成的包写入的文件重命名为最终位置) - 但如果您的用例对它们不敏感,那么您可以很好地使用简单的ParDo

此外,请注意Dataflow还没有用于流式传输的自定义接收器API,因此如果这是一个流式传输管道,那么ParDo肯定是正确的选择。

在您的ParDo中,您可能希望实施对Firebase的调用批处理,以避免每次调用开销。您可以使用DoFn.finishBundle()执行此操作(即,将批量更新保留在缓冲区中,在processElement中附加到其中,并在它变得过大且在finishBundle中最后一次时)将其刷新。请参阅this answer中类似模式的示例。