2

我有很多圖像需要通過java程序運行以創建更多圖像文件 - 這是一個令人尷尬的並行情況。每個輸入文件大約500 MB,在處理過程中需要大約4 GB的內存,並需要30秒到2分鐘才能運行。 Java程序是多線程的,但是對輸入文件的並行處理比使用更多的線程有更多的收益。我需要每天啓動多個進程(我不想手動打開/關閉羣集,也不需要全天候付費)。使用雲服務的並行文件處理

我有點在各種雲的選擇了丟失:

  • 亞馬遜lambda具有系統資源不足(沒有足夠的內存)。
  • Google Cloud DataFlow,似乎我將不得不編寫自己的管道源以使用其雲存儲桶。很好,但我不想浪費時間做這件事,如果這不是一個合適的解決方案(這可能是,我不知道)。
  • Amazon data pipeline看起來等同於Google Cloud DataFlow。 (在編輯中添加完整性
  • Google Cloud Dataproc,這不是一個地圖/減少hadoop-y的情況,但可能仍然有效。我寧願不管理自己的集羣。
  • 谷歌計算引擎或自動縮放的AWS,我剛剛啓動機器上每個核心的進程。從我的更多管理,但沒有API學習。
  • 微軟Data Lake尚未發佈,看起來hadoop-y。
  • 微軟Batch似乎很合適(但我問,因爲我仍然對其他選項好奇)。

任何人都可以建議適當的解決方案是什麼?

+0

是否有某個特定原因希望避免Hadoop(或Spark)進行此處理?我認爲這是因爲你不必重寫你的應用程序,但我想要求確定。 :) – James

+0

@James我不熟悉Spark/Hadoop,所以我的理由可能有缺陷。 Java程序是一個很大的第三方程序,實際上不能被重寫。 (雖然它可以通過API封裝在另一個Java類中)。我看到的實際方法是調用系統進程,這似乎使Spark/Hadoop變得不合適。 ...也許? – ZachB

+1

明白了。是的,你可以將它包裝在另一個Java類中並運行它。它會很快並且分發,但可能不夠優雅。對於Cloud Dataproc,一旦創建了集羣,它就會爲您管理,因此整體管理水平會很低。您也可以根據需要動態調整羣集大小,這可能很不錯。如果你很好奇,LMK(但我不想這個問題:) – James

回答

4

你應該可以很容易地用Dataflow做到這一點。該管道可能看起來像(假設你的文件位於Google Cloud Storage,GCS):

class ImageProcessor { 
    public static void process(GcsPath path) { 
     // Open the image, do the processing you want, write 
     // the output to where you want. 
     // You can use GcsUtil.open() and GcsUtil.create() for 
     // reading and writing paths on GCS. 
    } 
} 

// This will work fine until a few tens of thousands of files. 
// If you have more, let me know. 
List<GcsPath> filesToProcess = GcsUtil.expand(GcsPath.fromUri("...")); 
p.apply(Create.of(filesToProcess)) 
.apply(MapElements.via(ImageProcessor::process) 
        .withOutputType(new TypeDescriptor<Void>() {})); 
p.run(); 

這是案件的普通家庭中,數據流被用作embarassingly平行編排框架,而不是一個數據處理的一個框架,但它應該工作。

您將需要Dataflow SDK 1.2.0以使用MapElements轉換(支持Java 8 lambdas在1.2.0中爲新增功能)。

+1

我似乎需要指定一個編碼器。是否有一個可以用於'GcsPath'或者我需要實現自己的?或者我應該轉換爲'String'並在處理器中創建新的'GcsPath's? – ZachB

+1

轉換爲字符串可能是最簡單的。或者你可以使用SerializableCoder.of()。 – jkff

+1

謝謝。完整的最小示例[這裏](https://gist.github.com/zbjornson/ac6a378129f1675ca5ff?ts=4)。 – ZachB