数据管理(Data management)对于任何资源型站点都是一项艰巨而又重要的挑战。随着指数级增长的海量数据和多媒体的日益流行,甚至是小型的资源行站点也必要进行有效的管理和发布大量的数据。另外,如果简易的站点外数据资源管理(offsite storage resource)带来工作的省心,想必对于所有站点维护人员都是一大福音。
在SundayMorningRides.com上,我们为终端用户们管理数据量不断持续增长的GPS(全球定位系统),GIS(地理信息系统)数据和网页内容(文字,图像,视频等)。除此之外,我们还必须有效地管理日常的网站快照,备份以及网站和辅助软件的多个开发版本。对于任何小型组织,这些工作将显著地增加成本,不仅仅是启动资金的一次性投入,还包括持续的后续管理和维护人力成本。
.
Amazon Simple Storage Service(简称S3)就针对为解决上述在线数据管理的问题而应运而生。其目标是提供“可靠,快速,廉价的数据存储架构”-- Amazon就是用S3来支持它全球站点的运行。“Amazon S3提供的网络服务接口允许开发者存储和读取任意大小的数据。S3对于SundayMorningRides之类的公司具有相当的吸引力。因为它使我们从初始一次性成本投入和管理,维护以及服务器扩容的持续性成本这两座成本大山中解放出来。”
这篇文章涉及到 Perl,REST模型,以及Amazon S3 REST模块。整个过程通过开发一组在Unix命令行环境下的Perl工具与Amazon S3进行交互来实现。我另外会展示如何设置访问权限,以便于你可以直接从站点引用存储在Amazon S3上的多媒体文件和其他数据服务。
网络服务简介
网络服务(Web services) 已经成为一种发布信息的重要渠道(method of exposing information ),或者说是建立在网络形式上的一种服务( services via the Web)。本质上说,网络服务提供了两个连接网路之间资源的交互。Amazon S3 可以通过Simple Object Access Protocol(简单对象访问协议,SOAP)和representational state transfer (REST)两种访问实现。
SOAP接口通过组合各种特性(organizes features )生成定制操作(custom-built operations),同使用Java Remote Methond Invocation和Common Object Resource Broker Architecture (CORBA)一样,远程对对象(Objects)进行操作。区别于RMI和CORBA,SOAP使用HTTP请求中嵌入的XML作为应用程序的通讯协议。
和SOAP类似,REST同样使用HTTP协议进行传输。不同于SOAP,REST的操作遵循HTTP标准操作—GET,POST,PUT和DELETE。我倾向于把REST的CRUD(译者注:CRUD是Create(创建)、Read(读取)、Update(更新)和Delete(删除)的缩写)与操作关系型数据库的CRUD可以做一个类比:POST等同于创建(Create),GET等同于读取(Retrieve),PUT等同于更新(Update),DELETE等同于删除
Internet存储
Amazon S3 的数据存储里包含三个核心概念:对象(objects),容器(buckets),关键字(keys)
• 对象(objects)是在Amazon S3中最基础的实体单位,他们由对象(objects)数据和对象(objects)元数据组成。这里的元数据就是一组在HTTP头文件内预定义的属性值(name-attribute pairs)
• 容器(buckets)内包含多种对象(objects)。容器(buckets)内没有对象数量的限制,但是每个开发者最多只能拥有100个容器(buckets)。
• 关键字(keys)是识别对象(objects)的唯一标志。
为了避免在以上各种概念中纠缠不清,我比较喜欢这样的类比:容器(buckets)等同于文件夹,对象(objects)对应于文件,关键字(keys)看作是文件名。这样的理解的目的就是为每一个对象(objects)创建一个独特的HTTP名字空间。
我假定你已经在Amazon S3中注册,并且收到了Access Key ID和Secret Access Key。如果还没有,那请完成这些工作。
请注意:在Perl中不仅仅是S3::*模块可以连接Amazon S3.特别的是,Net::Amazon::S3模块隐藏了S3服务中的大部分细节。现在,我将使用一个相对简单的模块来解释S3内部是如何工作的。
连接,创建,显示容器(buckets)
连接到Amazon S3很简单,只要提供你的Access Key ID和Secret Access Key就可以建立一个连接,我们把这个连接返回给$conn.接下来讲解如何建立容器(buckets),显示容器(buckets)中间的内容。
#!/usr/bin/perl
use S3::AWSAuthConnection;
use S3::QueryStringAuthGenerator;
use Data::Dumper;
my $AWS_ACCESS_KEY_ID = 'YOUR ACCESS KEY';
my $AWS_SECRET_ACCESS_KEY = 'YOUR SECRET KEY';
my $conn = S3::AWSAuthConnection->new($AWS_ACCESS_KEY_ID,
$AWS_SECRET_ACCESS_KEY);
my $BUCKET = "foo";
print "creating bucket $BUCKET \n";
print $conn->create_bucket($BUCKET)->message, "\n";
print "listing bucket $BUCKET \n";
print Dumper @{$conn->list_bucket($BUCKET)->entries}, "\n";
print "listing all my buckets \n";
print Dumper @{$conn->list_all_my_buckets()->entries}, "\n";
Because every S3 action takes place over HTTP, it is good practice to check for a 200 response.
my $response = $conn->create_bucket($BUCKET);
if ($response->http_response->code == 200) {
# Good
} else {
# Not Good
}
正如你在输出中看到的:结果返回一个hash值。我用 Data::Dumper模块作为显示Bucket内容的工具。如果你是第一次运行这个,你在Bucket里面当然什么也看不到。
listing bucket foo
$VAR1 = {
'Owner' => {
'ID' => 'xxxxx',
'DisplayName' => 'xxxxx'
},
'Size' => '66810',
'ETag' => '"xxxxx"',
'StorageClass' => 'STANDARD',
'Key' => 'key',
'LastModified' => '2007-12-18T22:08:09.000Z'
};
$VAR4 = '
';
listing all my buckets
$VAR1 = {
'CreationDate' => '2007-11-28T17:31:48.000Z',
'Name' => 'foo'
};
';
by Abel Lin
创建对象(objects)
用HTTP PUT方法能快速地创建一个对象(objects)。不过要注意的是:覆盖一个已经存在的对象(objects)将不会有任何提示或者预防手段。Amazon S3实际过程中会自动更新那个读取最频繁的对象(objects)。同样,它目前还不能追加(append)或者修改(modify)单个对象(objects),只能通过替换的方式来达到追加(append)或者修改(modify)的单个对象(objects)。
my %headers = (
'Content-Type' => 'text/plain'
);
$response = $conn->put( $BUCKET, $KEY, S3Object->new("this is a test"),
\%headers);
Likewise, you can read a file from STDIN:
my %headers;
FILE: while(1) {
my $n = sysread(STDIN, $data, 1024 * 1024, length($data));
if ($n < 0) {
print STDERR "Error reading input: $!\n";
exit 1;
}
last FILE if $n == 0;
}
$response = $conn->put("$BUCKET", "$KEY", $data, \%headers);
To add custom metadata, simply add to the S3Object:
S3Object->new("this is a test", { name => "attribute" })
在默认情况下,每一个Object在写入数据时需要私有权限(private access control)。私有权限(private access control)只允许该对象(objects)的所有者读取。你可以改变这些权限设置,同样,要注意到每一个Object可以拥有最多5GB的数据容量。
你可能想问S3是否可以通过标准的HTTP POST的方法上传。那些在Amazon工作的同仁们正在努力达到这个目标—见《HTTP POST beta 纪要》(HTTP POST beta discussion)获取更多的信息。在他们完成这个目标之前,我们还只能通过中间服务器进行网页的形式上传。
读取对象(objects)
和创建Object类似,同样有多种方法从Amazon S3中读取数据。一种方法是生成一个临时的URL,用你喜欢的客户端(比如,wget或者Curl)甚至是一个浏览器访问这个临时的URL来显示和读取对象(objects)的内容。你要做的全部事情就是生成URL,然后用它来调用REST。
my $generator = S3::QueryStringAuthGenerator->new($AWS_ACCESS_KEY_ID,
$AWS_SECRET_ACCESS_KEY);
...and then perform a simple HTTP GET request. This is a great trick if all you want to do is temporarily view or verify the data.
$generator->expires_in(60);
my $url = $generator->get($BUCKET, "$KEY");
print "$url \n";
You can also programmatically read the data directly from the initial connection. This is handy if you have to perform additional processing of the data.
my $response = $conn->get("$BUCKET", "$KEY");
my $data = $response->object->data;
Another cool feature is the ability to use BitTorrent to download files from Amazon S3 . You can access any object that has anonymous access privileges via BitTorrent.
删除对象(Objects)
现在,可能在创建对象(Objects)过程中出错,或者卡死,那么你可能需要在同一节点上删除原来的对象(Objects)。
$conn->delete("$BUCKET", "$KEY");
设定访问权限和发布到网站
如果你已经注意到先前的例子,所有的Amazon S3 对象(objects)都是通过HTTP来访问。这样的情况使得Amazon S3像在线文件仓库一样特别实用。尤其是它对于管理站点和提供站点的多媒体方面非常实用。你可以几乎把Amazon S3服务看做是站点上一个迷你的Content Delivery Network。以下的例子说明如何建立一个简单的从Amazon S3动态引用图片构成的网页。
首先,上传图片并且设置ACL权限为公开(public)状态。我修改了先前的例子,使得Object能够被公开外部访问,需要把Header中 x-amz-acl设为Public-read
my %headers = (
'x-amz-acl' => 'public-read',
);
Additional ACL permissions include:
另外ACL的权限还包括
• 私有(默认设置)
• 公开读取(public-read)
• 公开读写(public-read-write)
• 授权读取(authenticated-read)
现在你已经对上述的代码娴熟于胸,通过对这些代码的整合,可以编写一个能够自动在网页上显示所有在容器(Bucket)内的图片的脚本。(你可能对格式会有一些美化排比处理)
...
my $BUCKET = "foobar";
my $response = $conn->list_bucket("$BUCKET");
for my $entry (@{$response->entries}) {
my $public_url = $generator->get($BUCKET, $entry->{Key});
my ($url, undef) = split (/\?/, $public_url);
$images .= "";
}
($webpage = <<"WEBPAGE");
$images
WEBPAGE
print $q->header();
print $webpage;
如果要向该页面添加图片,只需要上传的图片到对应的容器(Bucket)。之后这些图片会自动在你下次刷新页面的时候显示。
从网页引用多媒体文件同样是易如反掌。如果你观察这个例子生成的HTML,你会看见Amazon S3 URLs 拥有一个基本的格式:http://bucketname.s3.amazon.com/objectname 。另外,请注意:你的容器(Buckets) 的名字空间(namespace)是和其他Amazon S3 用户共享的。
结论
Amazon S3是一个强大的工具,它可以通过提供廉价和无限的存储空间帮助各种规模的组织进行数据管理。对于个人使用,它是一个非常好的备份工具(对于组织来说也是)和文件存储仓库。它也是一个优秀的协作工具。免去到处群发邮件的麻烦,只需要上传一个文件,并且设置合理的权限控制,就能进行有效的协作了。---再也不用纠缠于10MB附件大小之类的限制!
在SundayMorningRides.com ,我们用S3作为我们网站服务架构的一部分,来减少我们提供多媒体服务时候的硬件负载。
当和其他Amazon Web Service,比如SimpleDB(用于结构化的数据查询),Elastic Compute Cloud(用于数据处理)等等结合的时候,他们的组合往往能为网站提供计算和数据存储的低成本解决方案。