簡體   English   中英

使用動態日期時間從 Dataflow 寫入 Cloud Storage

[英]Write to Cloud Storage from Dataflow with dynamic datetime

我們正在構建一個寫入 Cloud Storage 的 Apache Beam (Java SDK) 管道。 我們使用TextIO.write()轉換來寫入存儲。 在此操作中,我們希望根據當前日期時間動態更改存儲文件的子目錄。

這是流管道的一部分。 理想情況下,我們希望部署它並讓 Beam 作業根據處理日期時間動態更改保存文件的文件夾子目錄。

我們當前的管道轉換如下所示:

DateTimeFormatter dtfOut = DateTimeFormat.forPattern("yyyy/MM/dd");

myPCollection.apply(TextIO.write().to("gs://my-bucket/%s", dtfOut.print(new DateTime()));

此代碼的問題在於,該函數返回的 DateTime 值與將管道部署到 Google Cloud Dataflow 時的值保持相同。 我們希望在處理傳入消息時根據日期時間動態更改子目錄結構。

我本來打算:

  1. 從 ParDo 函數獲取日期時間。
  2. 創建一個新的 ParDo 函數並將消息用作主要輸入,並將來自其他 ParDo 函數的日期時間作為輔助輸入傳遞。

這是最好的方法嗎? Apache Beam 中是否有可以解決我們用例的內置工具?

FileIO提供了 writeDynamic() 方法,該方法允許將 pCollection 的每個項目定向到給定項目本身的內容的不同目錄或文件。

我在下面放置了一個我創建的簡單示例,只是為了演示:

public class ExamplePipeline {
public static void main(String[] args) {
    PipelineOptions options = PipelineOptionsFactory.fromArgs(args).withValidation().create();
    Pipeline pipeline = Pipeline.create(options);


    Create.Values<String> sampleData = Create.of("ABC","DEF", "GHI");

    pipeline.apply(sampleData)
            .apply("WritingDynamic", FileIO.<PartitionData, String>writeDynamic()
                    .by(event -> new PartitionData())
                    .withDestinationCoder(AvroCoder.of(PartitionData.class))
                    .via(Contextful.fn(event -> event), TextIO.sink())
                    .to("gs://my-bucket/")
                    .withNaming(partitionData -> FileIO.Write.defaultNaming(partitionData.getPath(), ".txt")));

    pipeline.run().waitUntilFinish();
}

public static class PartitionData implements Serializable {
    private static final long serialVersionUID = 4549174774076944665L;

    public String getPath() {
        LocalDateTime writtingMoment = LocalDateTime.now(ZoneOffset.UTC);
        int year = writtingMoment.getYear();
        int month = writtingMoment.getMonthValue();
        int day = writtingMoment.getDayOfMonth();

        return String.format("%d/%02d/%02d/", year, month, day);
    }
}

上面的代碼將保存到一個結構中: gs://my-bucket/${year}/%{month}/%{day}/... .txt

by()方法中,我使用了我的數據分區器,我稱之為PartitionData

via()應該返回您想要最終作為內容寫入的內容。

to()將成為您路徑的基礎部分。

withNaming您真正構建了路徑的最后一部分。

通常我會在事件本身上有時間戳,告訴他們在現實中何時發生,然后你可以從事件中獲取而不是使用LocalDateTime.now

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM