簡體   English   中英

並行讀取S3中的多個文件(Spark,Java)

[英]Reading multiple files from S3 in parallel (Spark, Java)

我看到了一些關於此問題的討論,但無法理解正確的解決方案:我想將S3中的幾百個文件加載到RDD中。 我現在就是這樣做的:

ObjectListing objectListing = s3.listObjects(new ListObjectsRequest().
                withBucketName(...).
                withPrefix(...));
List<String> keys = new LinkedList<>();
objectListing.getObjectSummaries().forEach(summery -> keys.add(summery.getKey())); // repeat while objectListing.isTruncated()

JavaRDD<String> events = sc.parallelize(keys).flatMap(new ReadFromS3Function(clusterProps));

ReadFromS3Function使用AmazonS3客戶端執行實際讀取:

    public Iterator<String> call(String s) throws Exception {
        AmazonS3 s3Client = getAmazonS3Client(properties);
        S3Object object = s3Client.getObject(new GetObjectRequest(...));
        InputStream is = object.getObjectContent();
        List<String> lines = new LinkedList<>();
        String str;
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            if (is != null) {
                while ((str = reader.readLine()) != null) {
                    lines.add(str);
                }
            } else {
                ...
            }
        } finally {
            ...
        }
        return lines.iterator();

我從Scala中為同一個問題看到的答案中“解釋”了這個。 我認為也可以將整個路徑列表傳遞給sc.textFile(...) ,但我不確定哪種是最佳實踐方式。

潛在的問題是在s3中列出對象的速度非常慢,並且當某些事情進行了樹木行走時(如路徑的通配符模式加工),它看起來像目錄樹的方式會導致性能下降。

帖子中的代碼正在進行全子列表,這提供了更好的性能,它實際上是Hadoop 2.8和s3a listFiles(路徑,遞歸)附帶的HADOOP-13208

獲得該列表后,您已經獲得了對象路徑的字符串,然后您可以將其映射到s3a / s3n路徑,以便將spark作為文本文件輸入處理,然后您可以將其應用於

val files = keys.map(key -> s"s3a://$bucket/$key").mkString(",")
sc.textFile(files).map(...)

根據要求,這是使用的java代碼。

String prefix = "s3a://" + properties.get("s3.source.bucket") + "/";
objectListing.getObjectSummaries().forEach(summary -> keys.add(prefix+summary.getKey())); 
// repeat while objectListing truncated 
JavaRDD<String> events = sc.textFile(String.join(",", keys))

請注意,我將s3n切換為s3a,因為如果您的CP上有hadoop-awsamazon-sdk JAR,則s3a連接器是您應該使用的連接器。 它更好,它是一個由人(我)維護和測試火花工作負載的那個。 請參閱Hadoop S3連接器的歷史

您可以使用sc.textFile讀取多個文件。

您可以傳遞multiple file url作為其參數。

您可以指定整個directories ,使用wildcards甚至CSV目錄和通配符。

例如:

sc.textFile("/my/dir1,/my/paths/part-00[0-5]*,/another/dir,/a/specific/file")

參考這個ans

我想如果你嘗試並行化,而閱讀aws將使用執行器,並絕對提高性能

val bucketName=xxx
val keyname=xxx
val df=sc.parallelize(new AmazonS3Client(new BasicAWSCredentials("awsccessKeyId", "SecretKey")).listObjects(request).getObjectSummaries.map(_.getKey).toList)
        .flatMap { key => Source.fromInputStream(s3.getObject(bucketName, keyname).getObjectContent: InputStream).getLines }

暫無
暫無

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

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