使用 Amazon S3 云服务轻松实现存储

借助 Amazon 的 Simple Storage Service 进入云计算

Amazon Simple Storage Service (S3) 是一个公开的服务,Web 应用程序开发人员可以使用它存储数字资产,包括图片、视频、音乐和文档。 S3 提供一个 RESTful API 以编程方式实现与该服务的交互。通过本文,您将了解如何使用开源的 JetS3t 库利用 Amazon 的 S3 云服务存储和检索数据。

Andrew Glover, 合伙人, ThirstyHead.com

Andrew Glover 是一位开发人员、作家、演讲家和企业家。他是 easyb 行为驱动开发(Behavior-Driven Development,BDD)框架的创始人,并与他人合著了三本书:Continuous IntegrationGroovy in ActionJava Testing Patterns。他在 ThirstyHead.com 上讲解各种与 Groovy、Grails 和测试相关的课程。可以通过 thediscoblog.com 与他联系,他会在此定期发布软件开发方面的博客。



2009 年 5 月 04 日

简介

是一个抽象的概念,表示松散连接在一起的计算机组,这些计算机共同执行某项任务或者服务,就像是使用一个单独的实体完成一样。此概念背后的架构也很抽象:每个云提供者都可以根据各自情况随意设计它的产品。软件即服务(Software as a Service,SaaS)是一个与云相关的概念,表示云向用户提供某种服务。云模型可以降低用户成本,因为他们无需购买软件和硬件也可以运行 — 服务提供者已经为用户提供了必要的组件。

云计算简介

尽管云计算这一术语并不新鲜(Amazon 在 2006 年就开始提供它的云服务),但从 2008 年起它才开始真正成为流行词,这期间,Google 和 Amazon 的云服务逐渐获得了公众的关注。 Google 的 App Engine 使用户能够在 Google 基础设施上构建和托管 Web 应用程序。连同 S3,Amazon Web Services 还包括 Elastic Cloud Compute (EC2) 计算 Web 服务,该服务可以在 Amazon 的基础设施上托管应用程序。其他公司也开始蠢蠢欲动,准备与 Amazon 和 Google 一决高下,其中就包括 Microsoft®的 Azure,甚至 Sun Microsystems(其云计算还没有正式推向市场)也想分一杯羹。 IBM® 最近宣布,它将提供 某些产品 供开发人员在 Amazon EC2 环境中使用。

以 Amazon 的 S3 产品为例。顾名思义,这是一个公开的服务,使 Web 开发人员能够存储数字资产(如图片、视频、音乐和文档等),以便在应用程序中使用。使用 S3 时,它就像一个位于 Internet 的机器,有一个包含数字资产的硬盘驱动。实际上,它涉及到许多机器(位于各个地理位置),其中包含数字资产(或者数字资产的某些部分)。 Amazon 还处理所有复杂的服务请求,可以存储数据并检索数据。您只需要付少量的费用(大约每月 15 美分 /GB)就可以在 Amazon 的服务器上存储数据,1 美元即可通过 Amazon 服务器传输数据。

Amazon 的 S3 服务没有重复开发,它公开了 RESTful API,使您能够使用任何支持 HTTP 通信的语言访问 S3 。 JetS3t 项目是一个开源 Java 库,可以抽象出使用 S3 的 RESTful API 的细节,将 API 公开为常见的 Java 方法和类。编写的代码越少越好,难道不是吗?充分利用其他人的成果也是不错的。在本文中您将看到,JetS3t 使 S3 和 Java 语言的工作变得更加简单,从根本上提高了效率。


S3 概述

理论上,S3 是一个全球存储区域网络 (SAN),它表现为一个超大的硬盘,您可以在其中存储和检索数字资产。但是,从技术上讲,Amazon 的架构有一些不同。您通过 S3 存储和检索的资产被称为对象。对象存储在存储段(bucket)中。您可以用硬盘进行类比:对象就像是文件,存储段就像是文件夹(或目录)。与硬盘一样,对象和存储段也可以通过统一资源标识符(Uniform Resource Identifier,URI)查找。

例如,在我的硬盘中,我有一个名为 whitepaper.pdf 的文件,它位于主目录中名为 documents 的文件夹中。相应的,该 pdf 文件的 URI 为 /home/aglover/documents/whitepaper.pdf 。在 S3 中,URI 有一点不同。首先,存储段只能是顶级的 — 无法像嵌套硬盘中的文件夹(或目录)一样进行嵌套。其次,存储段必须遵循 Internet 命名法则;句点旁边没有斜杠,名称不包括下划线等等。最后,由于存储段名称已经是 Amazon 域内的 (s3.amazonaws.com) 公共 URI 的一部分,存储段名称必须在所有 S3 中是惟一的。(好消息是每个帐户只能包含 100 个存储段,因此不用担心别人占用了所有的好名字)。

DNS 魔术

不用担心 S3 资产的 URL 。通过 Domain Name System (DNS) 和 CNAME(canonical name的缩写)记录,您可以将自定义程度更高的 URL 映射到 S3 的 URL 。这样一来,您就隐藏了您(或您的应用程序)依赖 S3 的事实!

存储段在 S3 中是 URI 的根。也就是说,存储段的名称将是指向 S3 中某个对象的 URI 的一部分。例如,如果我有一个名为 agdocs 的存储段以及一个名为 whitepaper.pdf 的对象,URI 将是:http://agdocs.s3.amazonaws.com/whitepaper.pdf 。

S3 还提供了指定存储段和对象的所有者和权限的能力,就像对待硬件的文件和文件夹一样。在 S3 中定义对象或存储段时,您可以指定一个访问控制策略,注明谁可以访问您的 S3 资产以及如何访问(例如,读和写权限)。相应地,您可以通过许多方式提供对您的对象的访问,使用 RESTful API 只是其中一种。


开始使用 S3 和 JetS3t

要开始使用 S3,您需要一个帐户。 S3 不是免费的,因此在创建帐户时您必须向 Amazon 提供一种支付手段(比如信用卡号码)。不用担心 — 不收初装费;您只需要为使用付费。对于本文的示例,只需要支付不到 1 美元的费用。

在创建帐户的过程中,您还需要创建凭据:访问密钥和秘密密钥(就像用户名和密码)。(您还可以获取 x.509 证书;但是,只有在使用 Amazon 的 SOAP API 时才需要使用该证书)。和任何访问信息一样,都必须保管好您的秘密密钥。因为任何人使用您的凭据访问 S3 时,您都将为此付费。因此,每当创建存储段或对象时,默认的行为是让所有内容都私有;您必须显式获取对外部世界的访问。

有了访问密钥和秘密密钥,您可以下载 JetS3t并使用它通过 RESTful API 与 S3 交互。

使用编程手段通过 JetS3t 登录 S3 可以分为两步。首先,必须创建一个 AWSCredentials 对象,然后将它传递到 S3Service 对象。AWSCredentials 对象非常简单。它将访问密钥和秘密密钥视为 StringS3Service 对象实际上是一个接口类型。因为 S3 同时提供 RESTful API 和一个 SOAP API,JetS3t 库可以提供两种实现类型:RestS3ServiceSoapS3Service。就本文而言(包括大部分 S3 事务),RESTful API 的简洁性让它成为一个很好的选择。

创建一个连接的 RestS3Service 实例很简单,如清单 1 所示:

清单 1. 创建一个 JetS3t 的 RestS3Service 实例
 def awsAccessKey = "blahblah" 
 def awsSecretKey = "blah-blah" 
 def awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey) 

 def s3Service = new RestS3Service(awsCredentials)

现在可以执行一些有趣的操作了:例如,创建存储段、添加一个影片,然后获取一个有时间限制的 URL 。实际上,这听起来像一个业务流程,不是吗?这是一个与发布有限资产(比如影片)有关的业务流程。

创建存储段

对于虚构的电影业务,我将创建一个称为 bc50i 的存储段。借助 JetS3t,该流程很简单。通过 S3Service 类型,您有几个选项。我更喜欢使用 getOrCreateBucket 调用,如清单 2 所示。顾名思义,调用该方法可能返回一个存储段实例(表示为 S3Bucket 类型的实例)或在 S3 中创建代码段。

清单 2. 在 S3 服务器上创建存储段
def bucket = s3Service.getOrCreateBucket("bc50i")

不要被我这个简单的代码示例所蒙蔽。 JetS3t 库的扩展性非常强。例如,您可以快速确定拥有多少存储段 —— 只需通过 listAllBuckets 调用请求一个 S3Service 实例即可。该方法返回一个 S3Bucket 实例数组。对于任何存储段实例,您可以询问它的名称和创建日期。更重要的是,您可以通过 JetS3t 的 AccessControlList 类型控制与之相关的权限。例如,我可以获取 bc50i 存储段实例,并允许任何人可以公开读取和编写,如清单 3 所示:

清单 3. 修改存储段的访问控制列表
def bucket.acl = AccessControlList.REST_CANNED_PUBLIC_READ_WRITE

当然,通过 API,您也可以随意删除存储段。 Amazon 甚至允许您指定创建存储段的地理位置。 Amazon 简化了存储实际数据的复杂性,但是您可以告诉 Amazon 要将存储段(及其内部所有的对象)放在美国或欧洲(当前可用选项)。

向存储段添加对象

使用 JetS3t 的 API 创建 S3 对象就像操作存储段一样简单。 JetS3t 库也很智能,可以负责处理与 S3 存储段内文件相关的内容类型。例如,我想向 S3 上传一段影片 nerfwars2.mp4,以便用户能够在有限的时间内观看。创建一个 S3 对象与创建常见的 java.io.File 类型一样简单,并能将 S3Object 类型与存储段关联,如清单 4 所示:

清单 4. 创建一个 S3 对象
def s3obj = new S3Object(bucket, new File("/path/to/nerfwars2.mp4"))

使用文件和存储段初始化 S3Object 之后,要做的所有事情就是通过 putObject 方法上传,如清单 5 所示:

清单 5. 上传影片
s3Service.putObject(bucket, s3obj)

使用清单 5 可以完成上传。现在影片位于 Amazon 服务器了,影片的键就是它的名称。当然,您可以根据需要重写该名称以调用其他对象。实际上,JetS3t API(以及 Amazon S3 RESTful API)公开了许多信息,供您创建对象时使用。我们知道,您还可以提供访问控制列表。 S3 中的任何对象都可以保存 API 允许您创建的其他元数据。之后可以通过该元数据的 S3 API(以及派生的 JetS3t)查询任何对象。


创建对象的 URL

到现在为止,我的 S3 实例有一个包含影片的存储段。实际上,我的影片可以通过以下 URI 获取:http://bc50i.s3.amazonaws.com/nerfwars2.mp4 。但是,只有我才能获取。(在本例中,我只能通过编程方式访问它,因为与所有内容关联的默认访问控制被设置为拒绝任何未授权访问)。我的目的是为选择的用户提供一种方式查看新影片(在有限的时间内),直到我开始收取访问费用(S3 也会提供帮助)。

图 1 展示了默认的访问控制。返回的 XML 文档(相应地显示在我的浏览器中)告诉我对当前资产的访问被拒绝(http://bc50i.s3.amazonaws.com/nerfwars2.mp4)。

图 1. Amazon 的安全机制
Amazon 的安全机制

创建一个公共 URL 是 S3 提供的一个便捷功能;实际上,使用 S3,您可以创建一个公共 URL,但只在一段时间内有效(例如,24 小时内)。对于我刚刚存储在 S3 服务器上的影片,我将创建一个 48 小时内有效的 URL 。然后我将向选定的用户提供该 URL,以便他们下载并观看(假定他们在两天内下载)。

要创建一个针对 S3 对象的时间敏感型 URL,您可以使用 JetS3t 的 createSignedGetUrl 方法,这是一个 S3Service 类型的静态方法。该方法采用一个存储段名称、一个对象键(在本例中是影片名,还记得吗?)、一些凭证(以 JetS3t 的 AWSCredentials 对象的形式)、截止日期。如果您了解所需的存储段和对象键,则可以通过清单 6 中的 Groovy 代码快速获取 URL:

清单 6. 创建一个时间敏感型 URL
 def now = new Date() 
 def url = S3Service.createSignedGetUrl( 
   bucket.getName(), s3obj.key, awsCredentials, now + 2)

使用 Groovy,我可以通过 + 2 语法轻松指定一个 48 小时的限定日期。得到的 URL 如下所示(只有一行):

https://bc50i.s3.amazonaws.com/nerfwars2.mp4?AWSAccessKeyId= 
   1asd06A5MR2&Expires=1234738280&Signature=rZvk8Gkms%3D

现在,通过该 URL,可以在浏览器中获得图 2 所示的内容:

图 2. 用于下载的 URL
用于下载的 URL

这个过程是不是很简单?通过几行代码,我在云中创建了一个安全资产,该资产只能通过特殊的 URL 下载。

利用 S3 完成时间敏感型下载

如果您的带宽和存储需求不稳定,则 S3 能提供很多帮助。例如,想想我演示的业务模型 — 影片在一年中特定的时间发布。在传统的存储模型中,您需要在某处机架上购买许多空间(或提供通向它的硬件和管道),很可能下载量很大,但随后会相对降低。但是,您不能根据需要付费。使用 S3,该模型将根据需要付费 — 公司在需要时为存储和带宽付费。更重要的是,S3 的安全特性可以帮助您进一步指定人们何时可以下载视频,甚至可以指定谁可以下载。

使用 S3 实现这些需求非常容易。在高水平上,创建一个受限的影片公共下载需要 4 个步骤:

  1. 登录 S3 。
  2. 创建存储段。
  3. 向存储段添加所需的视频(或对象)。
  4. 创建一个指向该视频的时间敏感型 URL 。

就是这样!


结束语

与传统存储模型相比,S3 的随需付费模型有很多明显的优势。例如,在自己的硬盘上存储音乐收藏,我必须预先花 130 美元购买一个 500GB 的存储单元。我没有 500GB 的数据可以存储,因此我为自己不需要的空间花费了 25 美分 /GB(虽然很便宜)。我还需要维护设备并支付电费。如果我使用 Amazon,我不需要预先为不重要的资产支付 130 美元。我只需要支付 10 美分 /GB,无需为管理和维护存储硬件付费。现在想想在整个企业范围内实现这些服务的好处。以 Twitter 为例,在 S3 上为 100 万个用户帐户存储图片。通过按照使用付费的方式,Twitter 不需要花费大量资金购买硬件基础设施来存储和提供图片服务,也不需要支出人力和部件成本来配置和维护图片。

云的好处还不止这些。您还可以实现低延迟和高可用性。假设存储在 Amazon 云中的资产遍布全世界,那么为各个位置提供内容的速度将会更快。更重要的是,由于您的资产分布在各种机器上,您的数据在一些机器(或部分网络)瘫痪时也能保持高可用性。

一言以蔽之,Amazon S3 的好处很简单:低成本、高可用性、安全。除非您是一个 SAN 专家,喜欢维护硬件资产来存储数据内容,但是 Amazon 可能比您做的更好。在资金紧张的时候,为什么还要将自己的资金提前预支在硬件上呢(不要忘了,硬件会随时间贬值)?

参考资料

学习

  • Amazon S3:访问 Amazon Simple Storage Service 的主页。
  • JetS3t:了解更多有关 JetS3t 工具箱和应用程序套件的内容。
  • 云计算:访问 IBM Cloud Computing Central 查找大量云资源。
  • 用 Amazon Simple Storage Service (S3) 在云中存储数据”(developerWorks,2009 年 4 月):本文讨论 Amazon Simple Storage Service (S3) 提供的可伸缩、高响应性的服务。了解用于与 S3 交互的工具,使用代码示例构建一个简单的 shell。
  • 浏览技术书店查找有关这些主题和其他技术主题的图书。
  • developerWorks Java 技术专区:查找各种有关 Java 编程方面的文章。

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, Web development
ArticleID=386782
ArticleTitle=使用 Amazon S3 云服务轻松实现存储
publish-date=05042009