前言:
这段时间来到了某大数据平台,做平台技术底座封装和一些架构等等,有结构化数据也有非结构数据,涉及到很多技术,自己也私下花时间去研究了很多,有很多纯技术类的还是需要梳理并记录,巩固以及复习。一个项目用到了几个云存储,其中就包括Amazon S3,这边就学习并记录和复习一下。
Amazon S3简介
Amazon 最早推出的两项云服务:EC2 和 S3。
- Amazon S3:Amazon Simple Storage Service(亚马逊简易存储服务);
- EC2 :Elastic Compute Cloud(弹性计算云,即云中的虚拟服务器);
- Amazon S3支持REST风格,即通过GET、PUT、DELETE、POST、PATCH操作服务端的资源;
- Amazon S3 操作:Service,Buckets和Objects。
- Service 只包括 GET 操作,就是返回所有的 Buckets 的列表。
- Object 顾名思义,是指存储在云端的文件,值得注意的是,S3 中并没有明确的文件夹的概念,而是通过指定 object 的路径来实现,比如说,object 可以为 “photos/1.jpg”。
- Bucket 拥有全局名,名称由用户定义,用来存放 Object,由于是全局名,所以要确保名字是别人没用过的。
S3 Http request headers
具体可以查看亚马孙官网
访问 Web 服务时,Http request headers 需要一些参数。主要包括:
- Date:当前 UTC 时间,形式为 “Wed, 01 Mar 2009 12:00:00 GMT”。
- Content-Length: 当对 Object 进行操作的时候,返回内容的长度,注意不要包括 headers 中的内容。
- Content-MD5:用 base64 编码文件内容的 MD5 值。
- Content-Type:资源的类型,比如:text/plain。
- Host:Get Service 时为“ s3.amazonaws.com”。在对 bucket 和 object 进行操作时,例如bucket的名字是“bucketname”,那么 Host 就是“bucketname.s3.amazonaws.com”。
- x-amz-meta- 和 x-am- 开头的:包括 Amazon 定义的一些元数据和一些特定的 header。后面如果出现会提到。
- Authorization:这个是最重要的,主要作用是签名,Amazon 根据的请求计算出一个签名值和这里计算的签名值进行比对,只有相同时,访问才是合法的。接下来对 Authorization 的计算方法进行详述。
Authorization 的计算方法
根据亚马逊Amazon 文档说明:
Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;
Signature = Base64( HMAC-SHA1( UTF-8-Encoding-Of(YourSecretAccessKey), UTF-8-Encoding-Of( StringToSign ) ) );
StringToSign = HTTP-Verb + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Date + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
CanonicalizedResource = [ "/" + Bucket ] +
<HTTP-Request-URI, from the protocol name up to the query string> +
[ subresource, if present. For example "?acl", "?location", or "?logging"];
CanonicalizedAmzHeaders = <described below>
- Authorization 是由”AWS {0}:{1}“组成的,第0个参数为你的 Access Key ID,需要注册了 AWS 之后得到,AWS 注册;第1个参数是计算出来的签名值。
- 签名值的计算方法是对一个 UTF-8 的字符串,用你的 Secret Access Key(同样在 Access Key ID 处获取)进行 SHA1 加密。
- StringToSign 字符串也需要满足一定的格式。如上所示,第一行是你的操作名,应该为 PUT、GET、DELETE、HEAD 和 POST 中的一种。第二行是内容的 MD5 值的 base64 编码,和 headers 中的 Content-MD5 值应保持一致。第三行是Content-Type,同样需要和headers中的一致。第四行 Date,和 headers 中的 Date 一致。
- 需要说明的是 CanonicalizedAmzHeaders 和 CanonicalizedResource。
- CanonicalizedAmzHeaders 就是把 headers 中的 x-amz- 开头的作为 key 转化为小写并按顺序排列,key 和 value 之间用冒号相连,用换行符“\n”把它们给连接起来。
比如说 headers 中有:
X-Amz-Meta-ReviewedBy: [email protected]
X-Amz-Meta-ReviewedBy: [email protected]
X-Amz-Meta-FileChecksum: 0x02661779
X-Amz-Meta-ChecksumAlgorithm: crc32
那么CanonicalizedAmzHeaders就是:
x-amz-meta-checksumalgorithm:crc32\n
x-amz-meta-filechecksum:0x02661779\n
x-amz-meta-reviewedby:[email protected],[email protected]
- CanonicalizedResource 是指规范化的资源。
- 如果访问资源没有指定 bucket,那么就是“/”;
- 如果包括 bucket,而不包括 object,那就是“/bucket_name/”,注意前后的“/”不要落了;
- 如果既包括 bucket,也包括 object,那么就是“/bucket_name/object_name”;
- 另外,有时候比如是访问 bucke t的 acl(访问控制列表 acess control list)时,object_name 就是 ?acl,因此这时 CanonicalizedResource就是“/bucket_name/?acl”,访问 object 的 acl 时,CanonicalizedResource 就是“/bucket_name/object_name?acl”。
- 需要说明的是,如果计算出的 CanonicalizedAmzHeaders 不为空时,要确保 CanonicalizedAmzHeaders 和 CanonicalizedResource 之间有换行符“\n”连接。
Amazon S3 REST API
Service
对 Service的 操作只包括 Get,即获取用户所有的 Buckets 列表。Request headers 除了通用的,没有其他的内容。比如
GET / HTTP/1.1
Host: s3.amazonaws.com
Date: date
Authorization: signatureValue
返回的 XML 中包括 Owner 和各个 Buckets,比如:
<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult xmlns="http://doc.s3.amazonaws.com/2006-03-01">
<Owner>
<ID>bcaf1ffd86f461ca5fb16fd081034f</ID>
<DisplayName>webfile</DisplayName>
</Owner>
<Buckets>
<Bucket>
<Name>quotes</Name>
<CreationDate>2006-02-03T16:45:09.000Z</CreationDate>
</Bucket>
<Bucket>
<Name>samples</Name>
<CreationDate>2006-02-03T16:41:58.000Z</CreationDate>
</Bucket>
</Buckets>
</ListAllMyBucketsResult>
Buckets
由于项目中只用到了 Buckets 的 PUT、GET、DELETE,关于 acl、lifecycle、policy 等;
PUT Bucket
需要说明的是,在 request headers 可以加入 bucket 的权限控制,即指定 x-amz-acl,合法的值包括:private,public-read、public-read-write、authenticated-read、bucket-owner-read、bucket-owner-full-control,从名字就可以看出具体的含义。
- 在 request body 中可以包括位置信息,即用户期望 Bucket 放置在 Amazon 的哪个数据中心。
- 默认为 US Standard,其他数据中心包括 US West (Oregon) Region、US West (Northern California) Region、EU (Ireland) Region、Asia Pacific (Singapore) Region、Asia Pacific (Tokyo) Region、South America (Sao Paulo) Region。
- 对于我们中国用户来说,离得最近的是东京的数据中心。不过在 body 中内容中,这七个数据中心写成:‘EU’、 ‘eu-west-1’、‘us-west-1’、 ‘us-west-2’、‘ap-southeast-1’、‘ap-northeast-1’ 和 ‘sa-east-1’。
比如请求如下:
PUT / HTTP/1.1
Host: BucketName.s3.amazonaws.com
Content-Length: length
Date: date
Authorization: signatureValue
<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<LocationConstraint>BucketRegion</LocationConstraint>
</CreateBucketConfiguration>
GET Bucket
- Get Bucket 主要是列出这个 Bucket 下所有的 objects。值得提的是四个参数 Prefix、Marker、MaxKeys 和 Delimiter,利用这四个参数,可以达到多种效果。
- 首先是 Prefix,它表示这个 Bucket 中返回的 Object 以这个值为开头。Marker 表示,返回这个值以后的 Objects,比如说第一次调用没有返回全部结果,则把第一次调用返回的 Objects 的最后一个作为 Maker 调用,以返回其以后的 Objects。MaxKeys 返回单次请求返回的最大 Objects 数,默认为 1000。Delimiter 表示分隔符,是在设置了 Prefix 之后,能够返回共同的 Prefix(在结果中为 CommonPrefix)。
- 因此,通过设置 MaxKeys和Marker可以达到翻页效果,每次返回的最后一个 Object 作为下一次请求的 Marker,在返回值中,如果 IsTruncated 为 true,那么表示还有下一页。此外,通过设置 Prefix 和将 Delimiter 设为”/“,可以达到返回某个文件夹下所有内容的效果,其中 CommonPrefix 下的 Prefix 表示文件夹路径,而每个 Contents 中是 Object 的信息。
GET ?prefix=N&marker=Ned&max-keys=40 HTTP/1.1
Host: quotes.s3.amazonaws.com
Date: Wed, 01 Mar 2009 12:00:00 GMT
Authorization: AWS AKIAIOSFODNN7EXAMPLE:xQE0diMbLRepdf3YB+FIEXAMPLE=
返回结果为:
HTTP/1.1 200 OK
x-amz-id-2: gyB+3jRPnrkN98ZajxHXr3u7EFM67bNgSAxexeEHndCX/7GRnfTXxReKUQF28IfP
x-amz-request-id: 3B3C7C725673C630
Date: Wed, 01 Mar 2009 12:00:00 GMT
Content-Type: application/xml
Content-Length: 302
Connection: close
Server: AmazonS3
<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>bucket</Name>
<Prefix/>
<Marker/>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>my-image.jpg</Key>
<LastModified>2009-10-12T17:50:30.000Z</LastModified>
<ETag>"fba9dede5f27731c9771645a39863328"</ETag>
<Size>434234</Size>
<StorageClass>STANDARD</StorageClass>
<Owner>
<ID>75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a</ID>
<DisplayName>[email protected]</DisplayName>
</Owner>
</Contents>
<Contents>
<Key>my-third-image.jpg</Key>
<LastModified>2009-10-12T17:50:30.000Z</LastModified>
<ETag>"1b2cf535f27731c974343645a3985328"</ETag>
<Size>64994</Size>
<StorageClass>STANDARD</StorageClass>
<Owner>
<ID>75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a</ID>
<DisplayName>[email protected]</DisplayName>
Objects
PUT Object
PUT Object 基本操作类似,在 Http body 中添加 Object 的内容,这里就需要计算 Content-Type 等值。与
PUT Bucket 类似,可以在 Http headers 中加入 x-amz-acl,以控制 Object 的权限。
GET Object 在 GET Object 时,Response headers 中会包括这个 Object 的相关信息,除了
Content-Length 和 Content-Type 等,Etag 其实就是内容的 MD5 后的16进制的字符串。而 Response
body 中就是文件的内容。
版权归原作者 偷偷学习被我发现 所有, 如有侵权,请联系我们删除。