28

我正在开发一个包含文件存储和共享功能的项目,经过数月研究利用 AWS 的最佳方法后,我仍然有点担心。

基本上我的决定是使用 EBS 存储来存放用户文件还是 S3。当用户想要下载少量文件时,系统将包含即时 zip 归档。此外,当用户下载任何文件时,我不希望文件的 URL 暴露。

我想出的两个最佳选择是:

  1. 拥有一个 EC2 实例,该实例安装了多个 EBS 卷来存储用户文件。

    • 优点:它似乎比 S3 快得多,并且从 EBS 卷中压缩文件很简单。
    • 缺点:我相信亚马逊限制了你可以使用多少 EBS 存储,并且没有 S3 那样冗余。
  2. 文件上传和处理后,系统会将这些文件推送到 S3 存储桶以进行长期存储。当请求文件时,我将从 S3 检索文件并输出回客户端。

    • 优点:冗余,没有文件存储限制
    • 缺点:看起来很慢,无法将 S3 存储桶作为卷挂载在文件系统中,提供压缩文件意味着将每个文件传输到 EC2 实例,压缩,然后最后发送输出(再次,慢!)

我的任何假设有缺陷吗?谁能想到管理大量文件存储的更好方法?

4

5 回答 5

22

如果您的服务将被不确定数量的用户使用,请务必记住,可扩展性始终是一个问题,无论采用何种选项,您都需要扩展服务以满足需求,所以它会方便假设您的服务将在具有 EC2 实例池而不是单个实例的 Auto Scaling 组中运行。

关于保护 URL 只允许授权用户下载文件,有很多方法可以做到这一点,而无需您的服务充当中间人,那么您至少需要处理两个问题:

  1. 文件名可预测性:为避免 URL 可预测性,您可以将上传的文件命名为哈希并将原始文件名和所有权存储在 SimpleDB 等数据库中,您可以选择设置 http 标头,例如“Content-Disposition: filename=original_file_name.ext " 建议用户浏览器相应地命名下载的文件。

  2. 授权:当用户要求下载您的服务的给定文件时,使用查询字符串身份验证临时安全凭证为该特定用户发出临时授权,在一段时间内授予对该文件的读取访问权限,然后您的服务将重定向到 S3 存储桶 URL用于直接下载。这可以大大减轻您的 EC2 池实例的负担,从而可以更快地处理其他请求。

为了减少 S3 存储桶的空间和流量(记住您按存储和传输的 GB 付费),我还建议在上传到 S3 之前使用 gzip 等标准算法压缩每个单独的文件,并设置标题“Content-Encoding: gzip”为了使自动解压缩与用户浏览器一起工作。如果您选择的编程语言是 Java,我建议您查看我创建的插件代码webcache-s3-maven-plugin,以从 Web 项目上传静态资源。

关于压缩文件夹的处理时间,您经常无法确保文件夹会在短时间内被压缩,以便让用户立即下载它,因为最终可能会有巨大的文件夹可能需要几分钟甚至要压缩几个小时。为此,我建议您使用 SQS 和 SNS 服务以允许异步压缩处理,它的工作原理如下:

  1. 用户请求文件夹压缩
  2. 前端 EC2 实例在 SQS 队列中创建压缩请求
  3. 一个后端EC2实例,消费SQS队列的压缩请求
  4. 后端实例将文件从 S3 下载到 EBS 驱动器,因为生成的文件将是临时的,我建议选择至少使用带有临时类型磁盘的 m1.small 实例,这些磁盘是虚拟机本地的,以减少 I /O 延迟和处理时间。
  5. 生成压缩文件后,服​​务将文件上传到 S3 存储桶,可选择设置对象过期属性,这将告诉 S3 存储桶在一定时间后自动删除文件(再次降低您的存储成本),并且在 SNS 主题中发布文件已准备好下载的通知。
  6. 如果用户仍然在线,请阅读主题的通知,并通知用户压缩文件已准备好下载,如果一段时间后此通知未到达,您可以告诉用户压缩时间比预期的要长一旦文件准备好下载,该服务将通过电子邮件通知他。

在这种情况下,您可以有两个 Auto Scaling 组,分别是前端和后端,它们可能具有不同的可扩展性限制。

于 2012-08-11T13:39:18.197 回答
5

如果您坚持使用 S3 直接从您的 EC2 实例提供 zip 文件,这将比在本地存储它们更复杂。但是 S3 比任何 EC2 存储卷都更耐用,所以如果文件需要保存很长时间,我还是建议使用它。

您说您不想直接公开文件 URL。如果这只是因为您不希望人们能够为他们添加书签并在将来绕过您的服务身份验证,那么 S3 有一个很好的解决方案:

1 - 将您想要提供的文件(如果您希望这样,可以压缩)存储在私有 S3 存储桶中。

2 - 当用户请求文件时,对请求进行身份验证,然后将有效请求重定向到文件的签名临时 S3 URL。有很多不同语言的库可以创建这些 URL。

3 - 用户直接从 S3 下载文件,无需通过您的 EC2 实例。这可以节省您的带宽和时间,并可能为用户提供最快的下载速度。

这确实公开了一个 URL,但这可能没关系。如果用户保存 URL 是没有问题的,因为在你设置的过期时间之后它将无法工作。对于我的服务,我将时间设置为 5 分钟。由于是数字签名的,用户不能在不使签名失效的情况下更改 URL 中的过期时间。

于 2012-12-20T14:25:18.497 回答
2

对于此用例,使用 S3 是更好的选择。它可以更好地扩展,并且会更简单。你为什么担心它很慢?EC2 和 S3 之间的传输非常快速。

于 2012-08-11T00:53:06.243 回答
1

一些考虑:

  1. EBS 卷成本是 S3 的几倍。
  2. EBS 卷大小限制为 16 TB,因此这应该不是问题。但是,这种大小的卷非常昂贵。
  3. 确保您的存储桶与您的 EC2 实例位于同一区域。
  4. 使用 VPC 终端节点与 S3 通信。这要快得多。
  5. 确保您的 EC2 实例类型具有您需要的网络带宽。CPU 和网络速度随着实例大小而上升。

我会将所有内容保留在 S3 上,根据需要下载文件以将它们压缩到一个包中。然后将 zip 上传到 S3 并向用户提供一个 S3 签名 URL,以便从 S3 下载。

您可以允许用户从您的 EC2 实例下载,但很多用户会遇到错误问题、重试问题、带宽慢等。如果 zip 文件很小(小于 100 MB)在本地交付,否则上传到 S3 并让 S3处理用户下载问题。

另一种选择是创建一个 Lambda 函数来创建 zip 文件并存储在 S3 上。现在您不必担心网络带宽或扩展。Lambda 函数可以将您提供给浏览器的 S3 URL 返回给您,或者 Lambda 可以通过电子邮件向客户发送链接。为此请查看 SES。注意:Lambda 文件系统只有 512 MB 的空间,最多可以分配 1.5 GB 的内存。如果您生成的 zip 文件大于此大小,Lambda 将无法工作(此时)。但是,您可以创建多个 zip 文件(part1、part2、...)

于 2017-09-16T09:30:31.590 回答
0

主要问题是您在哪里托管。由于您说您使用的是 ec2 实例,这意味着您正在利用 AWS,如果您需要扩展,我会选择 EBS,然后选择 EFB。

S3 很棒,但 IMO 它主要用于如果您使用不同的提供商(如 Namecheap 等)托管您的网站,并且只想将 AWS 用于数据库。

我认为可靠性和持久性并不重要,尤其是当您考虑可以备份 Ec2 和 EFB 的快照时。

我会完全根据价格去。看看哪个更便宜。如果存在显着的性能差异(2-5 秒的用户等待时间),我可能会考虑花更多的钱购买更快的。

EFB 是一种扩展方法,可能比 EBS 便宜。我相信亚马逊建议使用 EBS 直到它达到一定大小,然后切换到 EFB。

于 2021-03-10T00:33:01.067 回答