【问题标题】:Is it possible to perform a batch upload to amazon s3?是否可以批量上传到亚马逊 s3?
【发布时间】:2013-02-24 08:53:41
【问题描述】:

amazon s3 支持批量上传吗? 我的工作需要每晚上传约 100K 的文件,这些文件最大可达 1G,但强烈倾向于小文件(90% 小于 100 字节,99% 小于 1000 字节)。

s3 API 是否支持在单个 HTTP 调用中上传多个对象?

所有对象都必须在 S3 中作为单独的对象可用。我无法在其他任何地方(FTP 等)或其他格式(数据库、EC2 本地驱动器等)托管它们。这是我无法更改的外部要求。

【问题讨论】:

  • 我可以问这些问题吗?
  • 我想知道为什么会出现这样的要求。如果您需要一次替换所有文件,也许有一些方法可以将它们以常规方式上传到临时存储桶,然后更改存储桶名称?
  • 你可以看看JetS3t,它在 S3 与多线程同步方面的功能非常全面。
  • 这个问题的公认答案仍然有效吗?已经 5 年了,所以只是好奇那段时间是否有任何变化......

标签: web-services amazon-web-services amazon-s3 cloud blob


【解决方案1】:

或者,您可以使用 sync 命令通过AWS CLI tool 上传 S3。

aws s3 同步 local_folder s3://bucket-name

您可以使用此方法非常快速地将文件批量上传到 S3。

【讨论】:

  • 与上一个答案一样,这里的含义似乎是这些工具正在以某种方式做一些通过 API 无法完成的事情,我不认为是这种情况
  • 我目前正在使用 AWS CLI 工具在本地目录和 S3 存储桶之间进行同步。我想知道是否有一个参数或参数可用于输出“上传”或将结果同步到本地 TXT 文件,然后我可以通过 blat.exe 将其通过电子邮件发送给某人。所有这些都将被放入一个批处理文件中,以计划同步数千个文件,这些文件将由我们的其他服务器下载。 (使用 S3 存储桶作为云源来克服我们源服务器的上传速度问题)
【解决方案2】:

s3 API 是否支持在单个 HTTP 调用中上传多个对象?

不,the S3 PUT operation 仅支持每个 HTTP 请求上传一个对象。

您可以在要与远程存储桶同步的机器上安装S3 Tools,然后运行以下命令:

s3cmd sync localdirectory s3://bucket/

然后您可以将此命令放在脚本中并创建一个计划作业以每晚运行此命令。

这应该做你想做的事。

该工具根据 MD5 哈希和文件大小执行文件同步,因此冲突应该很少(如果你真的想要你可以使用“s3cmd put”命令来强制盲覆盖目标存储桶中的对象)。

编辑:还要确保您阅读了我为 S3 工具链接的网站上的文档 - 您是否希望从存储桶中删除本地删除的文件或忽略等需要不同的标志。

【讨论】:

  • 此方法仍然使用单独的 put 操作,并且本质上并不比其他任何方法都快。答案已被接受,但似乎您所做的只是指向一个工具,该工具可以执行他在代码中可以执行的相同操作。
  • 您也可以从节点 api 进行同步 - 查看节点 s3-client
  • s3cmd 需要许可证才能继续使用
  • 关于 5 年后一次上传一个对象的答案是否仍然有效?
  • 我同意@bridiver
【解决方案3】:

调查

是否可以批量上传到 Amazon S3?

*

S3 API 是否支持在单个 HTTP 调用中上传多个对象?

没有。

说明

Amazon S3 API 不支持批量上传,但awscli 支持并发(并行)上传。从客户端和带宽效率的角度来看,这些选项的执行方式应该大致相同。

 ────────────────────── time ────────────────────►

    1. Serial
 ------------------
   POST /resource
 ────────────────► POST /resource
   payload_1     └───────────────► POST /resource
                   payload_2     └───────────────►
                                   payload_3
    2. Bulk
 ------------------
   POST /bulk
 ┌────────────┐
 │resources:  │
 │- payload_1 │
 │- payload_2 ├──►
 │- payload_3 │
 └────────────┘

    3. Concurrent
 ------------------
   POST /resource
 ────────────────►
   payload_1

   POST /resource
 ────────────────►
   payload_2

   POST /resource
 ────────────────►
   payload_3

AWS 命令​​行界面

how can I improve the transfer performance of the sync command for Amazon S3? 上的文档建议以两种方式增加并发性。其中之一是:

为了潜在地提高性能,您可以修改max_concurrent_requests 的值。此值设置一次可以发送到 Amazon S3 的请求数。默认值为 10,您可以将其增加到更高的值。但是,请注意以下几点:

  • 运行更多线程会消耗计算机上的更多资源。您必须确保您的机器有足够的资源来支持您想要的最大并发请求数。
  • 过多的并发请求会使系统不堪重负,这可能会导致连接超时或减慢系统的响应速度。为避免来自 AWS CLI 的超时问题,您可以尝试将 --cli-read-timeout 值或 --cli-connect-timeout 值设置为 0。

脚本设置max_concurrent_requests 和上传目录可能如下所示:

aws configure set s3.max_concurrent_requests 64
aws s3 cp local_path_from s3://remote_path_to --recursive

为了提供关于运行更多线程消耗更多资源的线索,我通过上传包含约 550 个 HTML 文件的目录(总共约 40 MiB,平均文件大小约 72 KiB)到 S3。下图显示了上传aws进程的CPU使用率、RSS和线程数。

【讨论】:

    【解决方案4】:

    为了补充大家所说的,如果您希望您的 java 代码(而不是 CLI)执行此操作而不必将所有文件放在一个目录中,您可以创建一个文件列表以上传和然后将该列表提供给 AWS TransferManager 的 uploadFileList 方法。

    https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferManager.html#uploadFileList-java.lang.String-java.lang.String-java.io.File-java.util.List-

    【讨论】:

      【解决方案5】:

      如果你想用Java程序来做,你可以这样做:

      public  void uploadFolder(String bucket, String path, boolean includeSubDirectories) {
          File dir = new File(path);
          MultipleFileUpload upload = transferManager.uploadDirectory(bucket, "", dir, includeSubDirectories);
          try {
              upload.waitForCompletion();
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
      

      如果您想测试,创建 s3client 和传输管理器以连接到本地 S3,如下所示:

          AWSCredentials credentials = new BasicAWSCredentials(accessKey, token);
          s3Client = new AmazonS3Client(credentials); // This is deprecated but you can create using standard beans provided by spring/aws
          s3Client.setEndpoint("http://127.0.0.1:9000");//If you wish to connect to local S3 using minio etc...
          TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(s3Client).build();
      

      【讨论】:

        【解决方案6】:

        这是一个全面的批处理解决方案,它使用单个调用 CommandPool::batch 将文件从一个文件夹复制到另一个文件夹,尽管在后台它为每个文件运行一个 executeAsync 命令,但不确定它是否算作单个 API 调用。据我了解,您应该能够使用此方法复制数十万个文件,因为无法将批处理发送到 AWS 以在那里进行处理。

        安装 SDK:

        composer require aws/aws-sdk-php
        
        use Aws\ResultInterface;
        use Aws\S3\S3Client;
        use Aws\S3\Exception\S3Exception;
        use Aws\S3\Exception\DeleteMultipleObjectsException;
        
        $bucket = 'my-bucket-name';
        
        // Setup your credentials in the .aws folder
        // See: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_profiles.html
        $s3 = new S3Client([
            'profile' => 'default',
            'region'  => 'us-east-2',
            'version' => 'latest'
        ]);
        
        // Get all files in S3
        $files = array();
        try {
            $results = $s3->getPaginator('ListObjects', [
                'Bucket' => $bucket,
                'Prefix' => 'existing-folder' // Folder within bucket, or remove this to get all files in the bucket
            ]);
        
            foreach ($results as $result) {
                foreach ($result['Contents'] as $object) {
                    $files[] = $object['Key'];
                }
            }
        } catch (AwsException $e) {
            error_log($e->getMessage());
        }
        
        if(count($files) > 0){
            // Perform a batch of CopyObject operations.
            $batch = [];
            foreach ($files as $file) {
                $batch[] = $s3->getCommand('CopyObject', array(
                    'Bucket'     => $bucket,
                    'Key'        => str_replace('existing-folder/', 'new-folder/', $file),
                    'CopySource' => $bucket . '/' . $file,
                ));
            }
        
            try {
                $results = CommandPool::batch($s3, $batch);
        
                // Check if all files were copied in order to safely delete the old directory
                $count = 0;
                foreach($results as $result) {
                    if ($result instanceof ResultInterface) {
                        $count++;
                    }
                    if ($result instanceof AwsException) {
                    }
                }
        
                if($count === count($files)){
                    // Delete old directory
                    try {
                        $s3->deleteMatchingObjects(
                            $bucket, // Bucket
                            'existing-folder' // Prefix, folder within bucket, as indicated above
                        );
                    } catch (DeleteMultipleObjectsException $exception) {
                        return false;
                    }
        
                    return true;
                }
        
                return false;
        
            } catch (AwsException $e) {
                return $e->getMessage();
            }
        }
        

        【讨论】:

          【解决方案7】:

          一个文件(或文件的一部分)=一个 HTTP 请求,但 Java API 现在支持高效的多文件上传,而无需您自己编写多线程,使用 TransferManager

          【讨论】:

          • “如果可能,TransferManager 会尝试使用多个线程一次上传单个上传的多个部分。”据我所知,它不会进行批量上传。
          猜你喜欢
          • 1970-01-01
          • 2013-10-29
          • 2012-03-30
          • 2012-07-07
          • 1970-01-01
          • 2022-08-07
          • 2017-08-01
          • 2010-10-17
          • 1970-01-01
          相关资源
          最近更新 更多