如何为项目构建高效的统一文件存储方案

Posted hushow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何为项目构建高效的统一文件存储方案相关的知识,希望对你有一定的参考价值。

1. 背景

在项目的建设过程中,遇到越来越多的第三方私有或公有化存储云服务,有阿里 OSS、华为云 OBS、七牛云 Kodo 等,各存储厂商对接标准备、数据、SDK 尽不相同,这对项目的实施和运维带来了很大的挑战,在和团队沟通以及调研过程中发现项目存在以下主要痛点

  • 项目中附件上传下载实现五花八门,代码难以维护
  • 存储参数配置凌乱,无法统一维护和配置,运维头大
  • 项目无法快速接入不同第三方云存储,业务要大改一通且维护不同的代码分支
  • 上传下载功能(前后端)常被业务重复开发,浪费资源
  • 通过网关、nginx 等简单包装代理方式处理第三方存储,丢失 CDN 及高可用性,浪费流量、计算时间等资源

所以急需为各项目开发一套统一的存储接入标准,屏蔽各厂商接入差异,增强业务快速实施及产品化的能力,为了解决以上问题,团队内部设计和打造了统一存储接入组件,至目前为止,已在众多项目落地实践,并得到大家的好评,同时也希望更多的小伙伴可以加入使用,后续也会准备将核心技术组件部分开源出来

2. 存储组件简介

统一文件存储组件是一个面向业务应用的文件存储抽象层,以插拔方式集各主流文件存储技术和数据于一身,目前已支持华为云OBS、阿里云OSS、Minio开源分布式存储、自研单机存储等,通过不同语言提供标准化的接口和使用方式,简便快捷的为业务开发支撑文件上传、下载、安全处理等能力

3. 存储组件特点

  • 统一简单存储接入标准,为业务屏蔽存储技术细节
  • 统一便捷的存储配置管理中心,达到快速运维能力
  • 可复用,节省产品或项目重复开发成本
  • 可扩展性,可接入更多第三方或自研类型存储服务

4. 功能一览

5. 整体设计

统一存储组件整体为了满足项目业务简便、轻量、扩展灵活、安全、性能等原则来设计的,主要职责是按标准进行接入,文件流不直接经过存储服务,这为业务大大节省了在性能、时间、资源上的消耗。

6. 上传资源场景

下图展示了一个前端浏览器上传资源的场景,描述是如何通过JS-SDK触发上传动作,拉取配置,获取凭证、推流等环节的;在设计JS-SDK前我针对各大主流对象存储平台进行了分析研究,最后将整个上传业务流程以及返回的数据模型进行了抽象,形成了一套标准的逻辑体系。

7. 下载私有资源场景

下载资源分两种,一种是公开资源,一种是私有资源,对于私有资源,业界的处理都是通过临时授权地址对资源进行下载或浏览的,所以关键问题就是要通过文件的标识去拿到这个临时仿问地址,同时业务需要考虑临时仿问地址的过期时间,以及为了安全需要通过后台服务调用JAVA-SDK才能拿到这个临时仿问地址。

8 应用存储接入配置

在项目使用统一存储前,需要在统一存储配置管理中添加配置,为应用分配存储类型(HUAWEI/TALKWEB/ALIYUN/MINIO)以及相关的第三方存储配置信息

9. java-sdk使用三步曲

为了简化使用,JAVA-SDK内置了SpringBoot自动装配机制,开关打开就支自动装箱IOC容器
当然为了非SpringBoot项目同时也是支持手工实例化方式。

9.1 添加依赖

<dependency>
    <groupId>com.talkweb.ssop</groupId>
    <artifactId>ssop-sdk-storage</artifactId>
    <version>1.0.2-SNAPSHOT</version>
</dependency>

9.2. 参数配置

ssop:
    storage:
        # 开关
        enable: true
        # 应用id,业务自己和SSO集成的时候对应的clientId,需要先提供给存储相关人员进行应用存储接入配置
        appClientId: 9cd96cc9-231a-4362-b654-0283e02daxxx
        appClientSecret: 9cd96cc9-231a-4362-b654-0283e02daxxx

9.3 使用示例

/**
 * demo
 * @author hushowly@foxmail.com
 * @date 2021/3/17 上午10:02
 **/
@Api(value = "spring控制器上传示例", tags = "上传示例")
@RestController
@RequestMapping("/version/fileDemo")
public class VideoDemoController 

    @Resource
    StorageClient storageClient;

    @PostMapping("/uploadFile1")
    public StorageFileDO uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception 
        StorageFileDO storageFileDO = storageClient.upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename(), multipartFile.getSize(), false);
        return storageFileDO;
    

    @PostMapping("/uploadFile2")
    public StorageFileDO uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception 
        String prefixPath = "moduleA/dirA";
        StorageFileDO storageFileDO = storageClient.upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename(), prefixPath, multipartFile.getSize(), false);
        return storageFileDO;
    

10. js-sdk 小试牛刀

js-sdk使用webpack+nodejs+typescript构建基于浏览器UMD规范lib包,实现不同的平台兼容性

10.1 引入封装好的 sdk 文件

<script src="./talkweb-main-sdk-2.0.0.js"></script>

10.2 初始化上传对象

//参数准备:
appId: 当前应用的Id,不可为空。
storageEndPoint: 统一存储服务接口地址,不可为空。
token: 请求存储服务时header中需要的token凭证,可以为空
timeout: 上传请求超时秒数,可以为空,默认300秒(大文件,建议使用分片上传方法)

//实例化上传对象
let talkwebStorage = new talkwebStorage.StorageClient( appId, storageEndPoint, token, 3000)

10.3 单文件上传

//上传参数,具体内容如下:
var fileParams= 
  file: file, //需要上传的文件file,不可为空。
  fileName: fileName, //文件名,不可为空。
  prefixPath: prefixPath, //文件路径,当前应用在桶中的相对路径,会体现在下载地址中,可为空,为空时,sdk自动生成一个随机目录。
  isPrivate: false  //文件是否为公开资源或私有资源 true 为私有, false 为公开资源,不可为空。
  //上传进度回调
  progressCallback: function(transferredAmount, totalAmount)
          console.log("已上传大小:"+transferredAmount+ " 总大小:"+totalAmount + " 进度:"+(transferredAmount*100/totalAmount))
      


//调用上传方法
talkwebStorage.upload( fileParams ).then(res => 
  console.log(res);
  console.log("上传成本");
).catch(err => 
  console.log(err);
  console.log("上传失败");
)

10.4 断点续传方法

  • 实例化对象
    参考以上10.2

  • 以断点续传方式上传(分片上传)

    talkwebStorage.uploadByResume(fileParams).then(res => 
    console.log(res);
    ).catch(err => 
    console.log(err);
    )
  • 暂停上传

    talkwebStorage.suspend();
  • 恢复上传
    talkwebStorage.restart().then((res) => 
    console.log(res);
    ).catch((res) => 
    console.log(res);
    alert("上传失败");
    );

以上是关于如何为项目构建高效的统一文件存储方案的主要内容,如果未能解决你的问题,请参考以下文章

如何为OpenStack云平台构建高可用存储设施?

如何为 C# 项目生成 .tlh 文件

如何为Android应用程序统一访问手机后退按钮

如何为ios构建skia

如何为ios构建skia

如何为 webapp 构建 phonegap 应用程序?