[英]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.