聊聊对象存储(cos、oss等)标准化

1,123 阅读8分钟

聊聊对象存储(cos、oss等)标准化

写作背景

“对象存储”可以说是开发中必不可少的,媒体文件(图片、视频、文件、音频...等)少则几 kb,大则几个 Gb,不可能把这些文件存储在数据库、服务器文件系统内,基本都会购买云服务厂商“对象存储”能力,它擅长存储和检索非结构化数据。列举一些“对象存储”产品优势:

  1. 廉价、扩容方便,可以说是无限扩容;

  2. 可靠性高,分布式架构和数据冗余保证数据可靠性;

  3. 管理简便,不需要复杂的文件管理系统,使用简单的 API 检索和存储;

  4. 全局访问,用户可以从全球各地访问对象存储中的内容,不同地域可能需要 cdn 加速;

  5. 安全性,提供私有存储、授权访问、授权上传方式控制用户读写”对象存储“内容;

  6. 成本低,基于使用量付费模式,渐进式按需购买容量无需过度投入。

对象存储厂商

对象存储厂商可选择性多,根据存储费用、折扣优惠、可靠性、市场份额、接入成本等指标自行选择。国内对象存储厂商:

  1. 阿里云(oss)OSS有哪些优势_对象存储(OSS)-阿里云帮助中心

  2. 腾讯云(cos)对象存储数据处理_COS数据处理_数据处理方案-腾讯云

  3. 华为云(obs)对象存储服务OBS_官网_云存储服务_数据云存储解决方案-华为云

  4. 百度云(bos)对象存储BOS_云存储_分布式存储_数据湖存储-百度智能云

业务需求

业务方需求比较简单,抽象成下面几种操作:

  1. 文件流上传;

  2. 文件删除;

  3. URL 转存;

  4. URL 签名;

  5. 文件元数据获取(大小、类型等)

  6. 文件下载,内网加速下载。

前端组件和后端 SDK 都需要包含这部分操作。另外,提供操作能力尽量克制,抽象共性并且是标准化能力,避免组件和 SDK 庞大,以及业务方接入成本高。

标准化

没有规矩做事不成方圆,这句话放在研发团队也同样适合。每个团队都标准,甚至每个研发都有自己的标准,最终的结果只会乱七八糟,能力复用性几乎为0。所以,定标准以及标准的宣导要到位。

桶分类

为了安全考虑划分私有读写桶和公共读写桶(对象存储服务商也是这么划分的)

  1. 私有读写桶,隐私文件比如:密钥、公司内部文件、通话录音等,这部分涉及隐私泄漏问题,私有读写桶文件访问需要做签名;

  2. 公共读写桶,用户可以直接访问、分享的,比如:公众号文章内的图片、视频等,公共读写桶文件访问可以挂 cdn 加速。

公共读写桶和私有读写桶划分要结合公司的业务来定。

桶分配

桶分配问题是比较难的,公司团队和业务方向比较多的情况,如果没有分配标准会导致后期用法混乱,你是否遇到过大部分业务场景媒体文件堆积到某一个桶内,再加上桶的目录定义不规范后期维护非常头疼。常见一些分配方案:

1.  按照团队分配桶(订单,商品团队,平台架构团队,营销团队,客服团队等);

2.  按业务模块划分桶,每个模块都有各自的桶;

3.  按业务方向划分,每个业务大方向一个桶。

先说结论,目前我的经验来看,按业务方向划分是比较靠谱的;每个模块一个桶既浪费资源,后期维护成本高;按团队划分也是不可取的,团队不稳定,某个团队的业务线随着业务发展可能会和其它团队业务线合并;

数据安全性

安全性问题是值得我们关注的,比如身份验证和授权用户才能上传、访问对象存储资源。安全性我们发挥的空间不是特别多,主要关注3点 key/secret 存储、上传、下载/访问控制。

  1. 关于 key 和 secret,建议大家不要放在应用配置文件内,最好是环境变量中,应用启动时读取,也可以提供一些加密解密算法防止泄漏;另外,key 和 secret 使用限制在某个关键应用内,暂时叫“对象存储应用”吧;

  2. 文件上传必须授权,最常用方案是通过“对象存储应用”颁发临时 token,权限最好控制在文件级别(比如:xx/yy/1.png),假设被篡改成 xx/yy/2.png,当前颁发临时 token 无法上传成功。另外,上传分后端业务上传和前端业务上传,最好提供标准“前端组件”、“后端 SDK”,对业务方透明,不需要关注上传细节,“前端组件”和“后端 SDK”不关注 key 和 secret ,拿到临时 token 上传;

  3. 文件下载/访问,如果是公共读写桶,桶内文件可以任意访问,不需要授权,可挂在 cdn 加速;如果是私有读写桶文件不可被任意访问,需要对 URL 签名才可访问,一般做法是原 URL-->对象存储应用签名-->目标 URL-->用户访问。签名有时间限制,根据业务场景定义过期时间。

文件路径

文件路径标准化,要考虑几点:

  1. 可读性强

    a. 层级不能太深;

    b. 不带特殊字符。

  2. 考虑归档

    a. 考虑用户ID放在一级目录,若用户流失,回收当前用户容量;

    b. 按照业务模块ID放在一级目录,若模块下线,回收当前模块的容量。

  3. 考虑用户容量使用以及收费策略

    a. 用户ID放在一级目录。

  4. 考虑统计类需求

    a. 按天上传文件个数、容量等。

  5. 文件名统一生成算法,避免特殊字符

假设划分3级路径

一级路径

用户ID等

二级路径

模块标识(订单、购物车等)

三级路径

日期(年月日)

文件名

统一算法生成

最终路径参考:0001/order/20241031/xxhy.png

系统边界

完成需求分析和定完标准下面进入设计阶段了,首先厘清业务边界,确定每个团队、甚至组件、SDK 的职责。

image.png

关键描述

  1. 对象存储服务商对接统一由“对象存储应用”对接,对业务方透明,业务方无需关心细节;

  2. ”前端通用组件“和“后端SDK”承接业务方所有需求,分别专注于上传、下载、签名、元数据获取等,封装 S3 标准协议,支持多平台上传;

  3. 数据上传后需要埋点上报后端应用,上传明细归档,主要用于后期统计类需求。

详细设计

支持多平台

不同对象存储服务商,认证体系、签名体系是不同的。所以,不能用S3协议完全兼容这部分,需要根据不同的配置调用不同服务商接口。这里最好最配置映射,采用策略模式调用不同服务商接口即可,策略模式可参考往期文章策略模式GO版本「附详细案例」 - 掘金

另外,S3 协议开源库 github 搜就可以了,java、go 等版本都有,大文件最好支持分片上传,这里不赘述。

最后,媒体文件上传不要经过后端应用上传,在“后端sdk”、“前端组件”内封装上传操,依赖“后端sdk”、“前端组件”应用负责文件上传;文件增、删、改必须认证拿到token后再执行对应操作。

模型设计

模型设计比较简单,保存上传文件明细即可,这步可以通过“前端组件”、“后端SDK”埋点。文件记录模型用处不小,比如统计全平台容量、按天统计、按用户统计、按模块统计等,可扩展性更强。

image.png

另外,文件上传后基本不是单独投放的,放在文章、表单等素材内;如果有必要可增加一张“文件记录和素材实体的映射表”。

接口设计

对象存储应用

  1. token 凭证获取;

  2. URL 签名;

  3. 媒体文件元数据;

”前端组件“和”后端SDK“

  1. 文件流上传;

  2. 文件删除;

  3. URL 转存;

  4. URL 签名;

  5. 文件元数据获取(大小、类型等);

  6. 文件下载,内网加速下载。

总结

  1. 可能有人会问为啥要支持多平台,在我看来有下面几种原因:

    a. 成本考虑,未来更换不同云厂商;

    b. 私有化部署考虑,比如你用阿里云,某些客户只用华为云,处于运维成本考量,客户很难接受更换云厂商,这部分成本肯定会转移给你。

    c. 如果架构设计阶段预留了支持多平台扩展,开发这类需求周期会大大减少;另外,支持多平台设计不难,并没有增加多少研发成本。

  2. 对象存储标准化不难,只需要做好定标准和标准宣导,技术上提供便捷的“前端组件”和”后端SDK“业务方在版本中渐进式接入。

另外,送各位一句话,不要等到代码都烂成屎了才想到优化,成本是非常高的,日常迭代中多回顾代码,发现潜在问题及时优化。