簡體   English   中英

Apache 光束管道攝取“大”輸入文件(超過 1GB)不會創建任何輸出文件

[英]apache beam pipeline ingesting “Big” input file (more than 1GB) doesn't create any output file

關於計算的數據流模型,我正在做一個 PoC 來測試一些概念,使用 apache beam 和直接運行器(和 java sdk)。 我在創建讀取“大”csv 文件(約 1.25GB)並將其轉儲到輸出文件中時遇到問題,如以下代碼所示(我主要關注使用此數據流測試 IO 瓶頸) /beam 模型,因為這對我來說是最重要的):

// Example 1 reading and writing to a file
Pipeline pipeline = Pipeline.create();
PCollection<String> output = ipeline
    .apply(TextIO.read().from("BIG_CSV_FILE"));
output.apply(
    TextIO
        .write()
        .to("BIG_OUTPUT")
        .withSuffix("csv").withNumShards(1));
pipeline.run();

我遇到的問題是只有較小的文件才能工作,但是當使用大文件時,沒有生成輸出文件(但也沒有顯示錯誤/異常,這使得調試更加困難)。

我知道在 apache-beam 項目( https://beam.apache.org/documentation/runners/direct/ )的跑步者頁面上,它在內存考慮點下明確說明:

本地執行受本地環境中可用內存的限制。 強烈建議您使用足夠小以適合本地內存的數據集運行管道。 您可以使用創建轉換創建一個小的內存數據集,或者您可以使用讀取轉換來處理小型本地或遠程文件。

以上表明我遇到了內存問題(但遺憾的是沒有在控制台上明確說明,所以我只是想知道這里)。 我也很關心他們的建議,即數據集應該適合內存(為什么它不從文件中分部分讀取,而不是將整個文件/數據集裝入內存?)

我還想添加到這個對話中的第二個考慮因素是(如果這確實是一個內存問題):直接運行器的實現有多基本? 我的意思是,實現一段從大文件中分塊讀取並輸出到新文件(也是分塊)的代碼並不難,因此內存使用在任何時候都不會成為問題(因為這兩個文件都沒有完全加載到內存中 - 只有當前的“塊”)。 即使“直接運行器”更像是測試語義的原型運行器,是否期望它可以很好地處理大文件? - 考慮到這是一個為處理流媒體而構建的統一模型,其中窗口大小是任意的,並且在下沉之前大量數據積累/聚合是一個標准用例。

因此,不僅僅是一個問題,我非常感謝您對以下任何一點的反饋/評論:您是否注意到使用直接轉輪的 IO 限制? 我是否忽略了某些方面,還是直接執行者真的如此天真地實施? 您是否通過使用像 flink/spark/google 雲數據流這樣的合適的生產運行器來驗證,這個約束消失了?

我最終會與其他跑步者一起進行測試,例如 flink 或 spark整個數據流思想基於在統一批處理/流模型的保護下攝取、處理、分組和分發大量數據。


編輯(反映 Kenn 的反饋): Kenn,感謝這些寶貴的觀點和反饋,他們在為我指明相關文檔方面提供了很大幫助。 根據您的建議,我通過分析應用程序發現問題確實與 java 堆相關(不知何故從未在普通控制台上顯示 - 僅在分析器上看到)。 即使文件大小“只有”1.25GB,在轉儲堆之前內部使用量超過了4GB,這表明直接運行器不是“按塊工作”,而是確實將所有內容加載到內存中(正如他們的文檔所說)。

關於你的觀點:

1- 我相信序列化和改組仍然可以通過“逐塊”實現來很好地實現。 也許我對直接運行器應該具備的能力有錯誤的期望,或者我沒有完全掌握它的預期范圍,現在我將避免在使用直接運行器時進行非功能類型的測試。

2 - 關於分片。 我相信 NumOfShards 在寫入階段控制並行度(和輸出文件的數量)(在此之前的處理應該仍然是完全並行的,並且只有在寫入時,它才會使用盡可能多的工作人員 - 並生成盡可能多的文件 -明確規定)。 相信這一點的兩個原因是:首先,CPU 分析器始終顯示 8 個忙碌的“直接運行器”——反映了我的 PC 擁有的邏輯內核數量——這與我設置 1 個分片還是 N 個分片無關。 第二個原因是我從這里的文檔中了解到的( https://beam.apache.org/releases/javadoc/2.0.0/org/apache/beam/sdk/io/WriteFiles.html ):

默認情況下,輸入 PCollection 中的每個包都將由 FileBasedSink.WriteOperation 處理,因此輸出的數量將根據運行程序的行為而有所不同,但始終會產生至少 1 個輸出。 可以使用 withNumShards(int)控制寫入階段的確切並行度,通常用於控制生成的文件數量或全局限制連接到外部服務的工作線程的數量 但是,此選項通常會損害性能:它會向管道添加一個額外的 GroupByKey。

這里一件有趣的事情是,“額外的 GroupByKey 添加到管道中”在我的用例中是不受歡迎的(我只想要 1 個文件中的結果,而不考慮順序或分組),所以可能會添加一個額外的“展平”文件步驟,在生成 N 個分片輸出文件之后是更好的方法。

3 - 你對分析的建議是正確的,謝謝。


Final Edit直接運行器不用於性能測試,僅用於數據的原型設計和格式良好。 它沒有任何按分區拆分和划分工作的機制,並處理內存中的所有內容

有幾個問題或可能性。 我會按優先順序回答。

  1. 直接運行器用於使用非常小的數據進行測試。 它專為最大程度地保證質量而設計,性能並不是最重要的。 例如:
  • 它隨機打亂數據以確保您不依賴於生產中不存在的排序
  • 它在每一步之后對數據進行序列化和反序列化,以確保數據正確傳輸(生產運行者將盡可能避免序列化)
  • 它檢查您是否以禁止的方式改變了元素,這會導致您在生產中丟失數據

你描述的數據不是很大,一般情況下DirectRunner最終可以處理。

  1. 您已指定numShards(1) ,它明確地消除了所有並行性。 它將導致所有數據在單個線程中組合和處理,因此即使在 DirectRunner 上也會比它可能的速度慢。 通常,您會希望避免人為地限制並行性。

  2. 如果有任何內存不足錯誤或其他阻止處理的錯誤,您應該會看到很多消息。 否則,查看分析和 CPU 利用率以確定處理是否處於活動狀態將很有幫助。

上面的 Kenn Knowles 已經間接回答了這個問題。 直接流道不用於性能測試,僅用於原型設計和數據的良好形成。 它沒有任何按分區拆分和划分工作的機制,並處理內存中的每個數據集。 性能測試應使用其他運行器(如 Flink Runner)進行,這些運行器將提供數據拆分和處理高 IO 瓶頸所需的基礎設施類型。

更新:添加到這個問題的重點,這里有一個相關的問題: 如何處理(Apache Beam)高 IO 瓶頸?

而這里的問題圍繞着弄清楚直接運行器是否可以處理龐大的數據集(我們在這里已經確定這是不可能的); 上面提供的鏈接指向關於天氣生產運行程序(如 flink/spark/cloud dataflow)的討論,可以直接處理龐大的數據集(簡短的回答是肯定的,但請查看鏈接以進行更深入的討論) .

暫無
暫無

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

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