虽然我正在快速修复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?
答案 0 :(得分:5)
是的,这应该有效,假设您可以使用以下警告:如果出现故障,可以多次复制或重试捆绑包,即可以在同一个元素上调用您的processElement
调用时间,可能同时发生。
即使Dataflow会对结果进行重复数据删除(即只有一个成功调用的项目通过c.output()
发出,最终会产生PCollection
),重复删除副作用(例如进行外部API调用)是你的代码的责任。
自定义接收器API仅强调这些问题并提供一种处理它们的“模式”(通过提供具有唯一ID的bundle并提供钩子来提交成功结果 - 例如,基于文件的接收器将使每个bundle写入到唯一命名的临时文件,并且提交挂钩会将成功完成的包写入的文件重命名为最终位置) - 但如果您的用例对它们不敏感,那么您可以很好地使用简单的ParDo
。
此外,请注意Dataflow还没有用于流式传输的自定义接收器API,因此如果这是一个流式传输管道,那么ParDo
肯定是正确的选择。
在您的ParDo中,您可能希望实施对Firebase的调用批处理,以避免每次调用开销。您可以使用DoFn.finishBundle()
执行此操作(即,将批量更新保留在缓冲区中,在processElement
中附加到其中,并在它变得过大且在finishBundle
中最后一次时)将其刷新。请参阅this answer中类似模式的示例。