一、前言
后端服务基本都会提供文件上传功能,均会面临两种场景:
- 分布式场景:可以部署多台服务,提高可用性
- 微服务场景:服务拆分了,服务间的调用变复杂了
用户基本操作有:
- 上传
- 下载
那么下面根据两种场景进行分析。
(1)分布式场景
分布式场景好处:
- 可以部署多台,提高可用性
- 分担单个服务器压力,可接入更多请求
这里假设,用户上传后的文件存储在文件服务所在的服务器:
-
文件上传:上传某个文件服务(存储在服务器)
-
文件下载:要找到上传的文件,那么得访问具体文件服务(所在服务器)
当然满足这两需求,可以采用 IP Hash 方式,如图:
但我想每个文件服务无差别,可以横向扩展,这样可以引入分布式存储,如图:
(2)微服务场景
为了提供相同功能,统一管理,引入了微服务,每个服务单一处理某种功能。
现在有个需求,用户上传和下载文件得经过服务A授权,才能到文件服务中访问。
针对此需求,有三种处理方式:
-
暴力法:拷贝,直接访问分布式服务
-
通过服务间访问:用户直接访问服务A,服务A再调用文件服务
-
客户端直传:客户端直接上传到文件服务
-
暴力法:拷贝,直接访问分布式服务
这种方式,就打破了微服务拆分原则了。
- 通过服务间访问:用户直接访问服务A,服务A再调用文件服务
这种方式简单,文件也通过服务间访问调用。 但,一般服务间访问,例如
Dubbo、Feign都只适用于小报文。 例如,Feign传递文件就有BUG,它会将文件存储在内存中。
- 客户端直传:客户端直接上传到文件服务
这种方式可分:
- 客户端授权得到
token- 客户端凭借
token上传文件- 应用服务得到文件服务回调
二、分布式存储
目前,常用的分布式存储有:FastDFS、Ceph、HBase、go-fastdfs、minio 等。
分布式存储一般具备:
- 元数据存储
- 数据冗余
- 数据校验
- 数据压缩
- 数据加密
- 数据去重
介入了第三组件,增加了服务调用的复杂度,但解决了分布式访问扩展问题。
这里,我们先不探究分布式存储组件如何实现这些特性,假设它是一定可用。只需要关注其在应用层调用方式。
完整回调重传机制: