汤山归来,两天不碰电脑,如小钗所言,变聪明许多,思维逐渐活跃

构建存储服务这个话题困扰了我很久,直到今天洗澡的时候才把这个问题的解决方案大纲理清,与大家分析思路和方案

#背景介绍

###Open edX 关于Open edX就不做过多介绍了,误入本文的小伙伴可以翻阅我此前的这篇译文:关于Open edX[译文]

入坑已久的小伙伴,继续下翻好啦

###存储服务 这里谈论的存储服务,主要指为网站提供文件存储/分发功能的服务,包括js/css/img等静态文件,也包括用户上传的资源文件,诸如视频/图片和文档

之所以称之为服务而不是系统,是因为我把它视为一个抽象存在,实际上在技术人员看来,它只是一套对接云平台的接口。是存储云平台与Open edX之间的一个胶水层

出于七牛云完备的文档和对开发者的友好,我选择以七牛云为例来实现

#Open edX中的文件存储需求 我们进入主题,从需求说起。

Open edX中的文件存储需求主要包括

  • 课程团队私有仓库(文件夹),用于存取:
    • 课程相关的log,以便进一步做数据分析
    • 课程数据下载,诸如成绩单
  • 课程资料
  • 课程视频(重点之一)

其中涉及的技术点主要包括:

  • 文件权限控制
  • 文件操作(接口)
    • 上传
    • 下载
    • 管理
  • CDN
  • 流量监测(方便优化)
  • 并发访问

#思路 ###传统思路 实际上以上是很典型的文件存储需求,传统的思路是自己构建一个存储服务就好啦,租上机房,买来服务器,拉好光纤,做好磁盘阵列,写一个web服务来对外提供存储服务。如果访问量大,继续做CDN之类的优化,折腾之极,而且效果不理想

我们实际也这样做过,试着自行搭建管理系统(试过wagtail,seafile等),试着整合cas登录机制,都很折腾

这样面临的问题包括但不限于:

  • 时间成本高
  • 经济成本高
  • 系统不够健壮
  • 扩展性差

###基于云平台 今天的开发者可能是有史以来最幸福的开发者。云的崛起,使大多的计算资源以云的形式存在,我们只需要抽象使用即可。

付出经济的成本,我们就可轻松获得稳定、灵活的云服务,而把底层的复杂性屏蔽在外,开发者只需关注业务逻辑。

当然,存储也不例外

#技术细节 此前困扰我的一个问题是,处于对权限的控制,我们是不是需要所有文件都经过后端,然后同步到云

其实这个问题已经被云存储上考虑在内的,S3的解决方案最为完备,此后也被其他厂商跟进。但对此方案的论述似乎很少,或者这是架构的一个问题,本身就小众,关注者不多,我在网上一搜发现不少架构者有这种疑惑,但决绝方案比较晚近才比较完备

当我们能够描述问题的时候,已经解决了大半,尤其是在网络时代,你遇到的问题,其实几乎都被别人遇到过,你要做的是弄清问题所在领域和问题描述。then google它或是github它

seek, and you will find

###编程模型 programming-model

一般的云存储上传流程是:客户端(终端用户) => 业务服务器 => 云存储服务,这样多了一次上传的流程,会有上传延时,而且有带宽的浪费。但七牛引入了客户端直传,将整个上传过程调整为:客户端(终端用户) => 七牛 => 业务服务器

文件上传成功以后,七牛的服务器使用回调功能,只需要将非常少的数据(比如Key)传给应用服务器,应用服务器进行保存即可。

在七牛云存储中,整个上传流程大体分为这样几步:

  • 业务服务器颁发上传凭证给客户端(终端用户)
  • 客户端凭借 上传凭证 上传文件到七牛
  • 在七牛获得完整数据后,发起一个 HTTP 请求回调到业务服务器
  • 业务服务器保存相关信息,并返回一些信息给七牛
  • 七牛原封不动地将这些信息转发给客户端(终端用户)

下载和其他操作也于此类似。更多细节请看文档

由以上流程我们看到,这是一个灵活的机制,我们可以将自己的业务员逻辑轻松附在其上,诸如如果要控制用户级别的权限,那么只要在在后端将上传凭证和用户身份进行绑定即可。诸如此类

###将模型用于Open edX 后端层面,构建颁发凭证的rest 接口,利用凭证,我们可以做到用户或课程团队粒度的权限控制。

前端层面,将上传资源的按钮绑定到新的函数上。主要需要修改的地方并不多:诸如studio视频组件,论坛的图片上传等

你当然也可以实现功能更全面的资源管理,诸如实践课件资源库之类的功能,只需将云存储api作为积木,置于后端业务逻辑中即可

#我的实现

我会把我的实现放到我此前这个项目里edx_siteapi,欢迎围观,该项目的主要目的是对open edx进行拓展。

主要是实现权限控制和授权的rest api

###其他云平台 * 又拍云 * 阿里云 对象存储oss * python-sdk 快速入门

#FQA ###流量监控的用途 对于某个区域内高访问量的视频资源,采用区域内自行搭建视频服务器的方式可能比云服务廉价许多。但这依然不影响我们使用云存储。一般的云存储都有流量监控机制,当我们检测到某类文件流量高于临界值时,只需把它同步到自行搭建的本地服务器即可,后台修改地址即可,我们可以用编程的方式,为视频对象赋予一个use_local_file的开关(属性)即可

这样在享受云平台廉价、敏捷的同时,也可以对特定文件做本地优化(出于成本考虑)

之所以提到这点是因为公司前技术总监T老师构建了此前的视频解决方案,在特定情况下,要比云存储廉价。他说我遇见过最优秀的技术人员之一,尽管目前已经不再做技术,对问题的分解能力,交流与组织能力都令人叹服

###跨域问题 由于大多云存储网站都支持域名绑定,所以不错在跨域的问题,ajax可以照常使用。所以开发者感受不出文件服务是不是来自本地后端

###定制化的CDN 出于我们的具体需求,局域网内布有服务器。解决方案也简单,定制同步文件,而后匹配用户请求头,将静态资源重定向到坐在局域网服务器的ip即可,这个任务可以放在nginx那里处理

#参考 * 关键概念 * 编程模型 * Python SDK 使用指南 * JavaScript SDK 使用指南 * 上传策略(PutPolicy)

#相关问题 * 使用第三方存储,怎么不进行自己服务器中转就能进行权限控制? * 各种云储存都有一个问题