前言
本片文章主要介绍OSS存储的核心要点和客户端(web、app)如何基于OSS存储实现文件的上传和下载
引入目的
如果文件都保存在自己的服务器上,好处是方便简单快捷。客户端请求时只需要从服务器端的相对路径中获取文件即可。但是这样子做比较影响性能。而且该服务器还必须做好冗余备份等等,因为一旦磁盘损坏,文件就会缺失。费时费力费资源。
而基于云端的 OSS存储
,就能够完美的解决这些问题。我们可以将OSS存储当作是网盘。
通过将图片,文件等静态资源存储在OSS中,解放了传统方式对于公司服务器性能的影响,同时也提高了可靠性。并且可以对接云端的各种能力,比如对图片在线编辑、合规校验等等。
关键概念解析
以阿里云为例,其提供的OSS存储暴露了基于HTTP请求的功能接口。OSS存储的宏观物理架构可以看成图1.1所示:
阿里云部署的OSS服务具有多个 Region
,比如华东1(杭州)和华北1(北京)。北京地区的用户访问华东1的速度和访问华北1的速度肯定不一样。然后每个Region划分成了多个 Bucket
存储空间。每个 Bucket 存储空间中存储了实际的文件,即 Object
。
以下是关键概念:
- Region:不同地区的物理服务器集群。
- endpoint:每个 Region 对外暴露的访问地址
- bucket:Region 中的存储区块
- Object:相当于 bucket 中的文件
核心业务流程
用户购买了OSS服务后,即可创建 Bucket,创建时需要指定该 Bucket 需要从哪个 Region 划分出去。之后,就可以向该 Bucket 中上传文件了,即 Object。上传成功后,可以从OSS存储中获取需要的文件。
问题
该流程中,存在着两点需要明确的问题。
问题1:如何从OSS海量的文件中获取到需要的一个文件
即如何定位唯一的文件问题。
对于阿里云来说,OSS 存储服务是多租户的,而租户对应的其实是 Bucket。由于每个 Region 都有一个对外暴露的访问地址,并且访问 OSS 存储服务需要用到HTTP协议。
最终,阿里云规定了每个用户的上传/下载文件的HTTP请求中,请求头 Host
属性的值构成需要为:http://Bucket.endpoint
,
即通过 Bucket名字和Region的endpoint组成的子域名来唯一定位到某一个特定的 Bucket中。
那么,Bucket中的文件又是如何唯一定位的?
因为 Bucket 中没有目录这一概念,所有文件都是平级的,所以很容易想到,Bucket 中是通过文件名来唯一定位一个文件的。
综上,就解释了问题1.
问题2:上传文件时,文件名应该如何指定
该问题是由问题1引出的,所以文件名肯定需要保证唯一性。那么如何生成呢?
并不是说简单的比如用毫秒级时间戳 + 用户ID的组合来生成。如果是这样子的有顺序的前缀,则会影响客户端的请求性能。
原因如下:
OSS按照文件名UTF-8编码的顺序对用户数据进行自动分区,从而能够处理海量文件,以及承载高速率的客户请求。不过,如果您在上传大量对象时,在命名上使用了顺序前缀(如时间戳或字母顺序),可能会导致大量文件索引集中存储于某个特定分区。
该分区成为热点分区,导致分区的I/O能力被耗尽,或被系统自动限制请求速率。
那么,如何解决呢?
这里,阿里云官方提供了两种思路:
- 向文件名添加十六进制哈希前缀
- 反转时间戳文件名
具体上传文件的时候文件名是如何指定的,请大家参考各自的SDK包,SDK包中提供了随机文件名生成方法,请留心查看,了解一下。
web端上传
web端上传我们直接使用官方推荐的最佳实践。web端从服务器端获取到policy,其实就是token,然后再直接向OSS中上传文件即可。上传完成后,需要调用服务器相关的存储API,将该图片的地址发送给服务器,即 文件名
和 host
,二者已经再上文提到过了。
然后读取的时候先从服务器端获取到 文件名 和 host ,二者拼接起来就是图片的 URL ,即 文件名.host
。直接访问该 URL 即可。
每次上传图片,都需要获取一次 Policy。
参考资料
提供了SDK包和API接口
APP上传
其实和 web 端上传类似,但是这边获取的是叫做 STS凭证
,不知道为什么要分开而不是统一的 token。
总之,过程和 web 一样,参考资料不同。
参考资料
提供了SDK包和API接口
参考资料