OSS文件存储方案-阿里云

时间:2024-04-09 14:46:43

前言

本片文章主要介绍OSS存储的核心要点和客户端(web、app)如何基于OSS存储实现文件的上传和下载

引入目的

​ 如果文件都保存在自己的服务器上,好处是方便简单快捷。客户端请求时只需要从服务器端的相对路径中获取文件即可。但是这样子做比较影响性能。而且该服务器还必须做好冗余备份等等,因为一旦磁盘损坏,文件就会缺失。费时费力费资源。

​ 而基于云端的 OSS存储,就能够完美的解决这些问题。我们可以将OSS存储当作是网盘。

​ 通过将图片,文件等静态资源存储在OSS中,解放了传统方式对于公司服务器性能的影响,同时也提高了可靠性。并且可以对接云端的各种能力,比如对图片在线编辑、合规校验等等。

关键概念解析

以阿里云为例,其提供的OSS存储暴露了基于HTTP请求的功能接口。OSS存储的宏观物理架构可以看成图1.1所示:

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能力被耗尽,或被系统自动限制请求速率。

那么,如何解决呢?

这里,阿里云官方提供了两种思路:

  1. 向文件名添加十六进制哈希前缀
  2. 反转时间戳文件名

具体上传文件的时候文件名是如何指定的,请大家参考各自的SDK包,SDK包中提供了随机文件名生成方法,请留心查看,了解一下。

web端上传

OSS文件存储方案-阿里云

图2.1

​ web端上传我们直接使用官方推荐的最佳实践。web端从服务器端获取到policy,其实就是token,然后再直接向OSS中上传文件即可。上传完成后,需要调用服务器相关的存储API,将该图片的地址发送给服务器,即 文件名host ,二者已经再上文提到过了。

​ 然后读取的时候先从服务器端获取到 文件名 和 host ,二者拼接起来就是图片的 URL ,即 文件名.host 。直接访问该 URL 即可。

​ 每次上传图片,都需要获取一次 Policy。

参考资料

提供了SDK包和API接口

web最佳实践-服务端签名后直传

APP上传

OSS文件存储方案-阿里云

图2.2

其实和 web 端上传类似,但是这边获取的是叫做 STS凭证,不知道为什么要分开而不是统一的 token。

总之,过程和 web 一样,参考资料不同。

参考资料

提供了SDK包和API接口

快速搭建移动应用直传服务

参考资料

web端-java

app端-java