[英]Read from dynamic GCS bucket partitioned by date using Apache Beam and Dataflow
现在我正在将失败的记录从 API 调用发送到按天分区的 GCS 存储桶
前任:
gs://path/to/file/2022/07/01
gs://path/to/file/2022/07/02
ETC..
从那里,我想安排一个批处理作业,以在第二天使用 Apache Beam 和 Dataflow 重试这些失败的记录。 问题是 GCS 路径末尾的日期仅在初始模板上传到 GCP 时添加,并且无论何时运行类似于this和this的作业都保持在该日期。 我正在使用 ValueProvider 但我无法解决这个问题。
我发现当我在本地运行管道时,一切正常,但在 Dataflow 中,只有 expand 函数中的 DoFns 实际运行。
基本上我在这里做的是:
获取初始 gcs 路径并将当前日期减去 24 小时附加到fileMatch
的末尾
调用 FileIO.readMatches() 将每个match()
转换为ReadableFile
调用 MatchGCSFiles ,其中包含以下使用值提供程序获取当前日期并附加到 GCS 路径的确切代码。 我这样做是为了覆盖现有路径,因为这是让它工作的唯一方法,因为我认为我理解 DoFn 不能接受空输入(仍在学习 Beam)
再次调用FileIO.readMatches()
将新的match()
转换为新的ReadableFile
,然后调用 API。
String dateFormat = "yyyy/MM/dd"; ValueProvider<String> date = new ValueProvider<String>() { @Override public String get() { String currentDate = Instant.now().minus(86400000).toDateTime(DateTimeZone.UTC).toString(dateFormat); return currentDate; } @Override public boolean isAccessible() { return true; } }; ValueProvider<String> gcsPathWithDate = new ValueProvider<String>() { @Override public String get() { return String.format("%s/%s/*/*.json", gcsPathPrefix, date.get()); } @Override public boolean isAccessible() { return true; } }; fileMatch = FileIO.match().filepattern(gcsPathWithDate.get()); } PCollectionTuple mixedPColl = input .getPipeline() .apply("File match", fileMatch) .apply("applying read matches", FileIO.readMatches()) .apply("matching files", ParDo.of(new MatchGCSFiles())) .apply("applying read matches", FileIO.readMatches()). //problem here .apply("Read failed events from GCS", ParDo.of(new ReadFromGCS())) .apply(//call API)...
问题出在第二个 FileIO.readMatches() 中,返回类型不匹配:原因:不存在类型变量的实例,因此 PCollection 符合 PCollection
我为此尝试了不同的解决方法,但似乎都没有。
是否有另一种/更好的方法来动态添加/替换 GCS 路径中的日期? 我还在学习 Beam,所以如果我做错了什么,请告诉我。
提前致谢。
您似乎可以应用一些改进:
您的管道总是从昨天读取文件。 因此,您不需要运行时参数(并且在您的示例中使用 ValueProvider 是不正确的,因为它没有用作管道选项提供的运行时参数)。
public interface MyOptions extends PipelineOptions { @Description("Date in yyyy-MM-dd") @Default.String("2022-01-01") ValueProvider<String> getDateValue(); void setDateValue(ValueProvider<String> value); }
然后在你的 DoFns 中使用它。
... @ProcessElement public void process(ProcessContext c) { MyOptions ops = c.getPipelineOptions().as(MyOptions.class); // Use it. ...(ops.getDateValue()) } ...
当您开始工作时,您必须提供该任意日期的管道选项,就像您设置任何其他 PipelineOptions 时一样。
您始终可以通过使用 Date 获取昨天的日期来获取昨天的日期。
Instant now = Instant.now(); Instant yesterday = now.minus(1, ChronoUnit.DAYS);
然后直接在您的管道中使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.