文件存储系统映射模块原理解析
系统简介
近期我们开发了一套基于Fastdfs
的分布式文件存储发布系统,用于解决如下几个问题:
- 大量静态文件的存储和访问
- 停用原有的FTP管理模式
- 解决NAS存储单点的问题
在项目之初,为了实现满足这些需求的一套系统,查证了一些相关案例和开源组件,本着简单可依赖的原则,最后确定为采用Fastdfs
作为存储平台,之所以是Fastdfs
,也是觉得一是公司的某些业务线已经在使用,其可用性和稳定性已得到一定检验;二是Fastdfs
作为国内的一款开源软件,资料较多且使用成本较低。
核心思路
因底层存储系统采用了开源实现,那么我们的核心就是做一个简单易用的文件管理端和发布站点,使用过Fastdfs
的同学应该知道,通过其client api上传文件后,得到的是一个通过哈希散列计算后的文件名,无法使用原始文件名进行访问,如果是一般的文件存储(例如一些广告背景图等),可能问题也不大,但如果是发布一个促销专题页面,那么这个工作将变得极其困难,因为一个促销专题页,往往同时包含所依赖的样式文件、背景图片、脚本等,页面html中一般是依赖的相对路径,所以如果直接上传到Fastdfs
则文件路径依赖的问题无法解决,或者说要很麻烦的方式解决。
因此,我们引入了映射模块,用来处理逻辑地址和物理地址的对应关系。在本文中也将主要针对映射模块做一个比较详细的介绍和分析。
主要具备如下功能和特点
该系统目前已经上线,主要具备如下功能和特点:
- 基于目录层级的文件、权限管理方案
- 文件发布支持多域名
- 分布式系统保证高可用和稳定性,易于横向扩展
- 映射模块基于
Nginx
内部原理实现 - 支持文件版本管理,支持回滚操作
该系统包含三个模块:
-
管理模块
一套基于HTML的UI界面,可进行系统管理、文件管理等功能。
-
映射模块
负责解析用户请求,并利用Nginx内部特性来返回数据。
-
存储模块
完全基于Fastdfs实现,易于扩展,要求安装fastdfs-nginx-module。
映射模块介绍
映射模块就是一个部署于Tomcat
之上的web站点,其职责就是接受前端Nginx转发过来的请求,把一个URL地址转换为fastdfs
存储的物理地址,并返回给Nginx
,Nginx
拿到物理地址后读取文件并返回给用户。
Nginx
作为高性能的反向代理服务器,在本模块中起到的作用不仅仅是负载均衡,还利用到了Nginx的一个内部特性sendfile
,利用该特性,Tomcat
作为映射模块仅需要处理映射关系,而不用处理文件IO操作,而我们知道,应用程序服务器上的性能瓶颈往往是IO操作,通过部署这样的系统结构,得以提高系统的整体性能。
为什么需要加入映射模块
既然底层的存储是基于Fastdfs
实现,那么利用fastdfs-nginx-module
,完全可以通过文件的物理地址进行访问,只需要做一个GUI来进行文件的管理即可,这也是很多存储系统的实现方式。现加入映射模块,除了解决上文提到的发布促销页面的问题,其意义还在于:
- 文件的URL地址由复杂变为简单可理解,易于阅读且对SEO友好。
- 文件的组织方式变得有序、可管理。
- 基于目录树的结构,易于权限的控制和管理。
- 发布站点多域名支持、性能扩展更为容易。
映射模块工作流程
完整的映射模块包含如下几个部分:
- Nginx(同时起到负载均衡和读取文件的作用)
- Tomcat 站点(处理url和物理地址对应关系的程序逻辑)
- MySQL(逻辑url和物理url mapping关系存储)
现以用户请求一个文件为例,来说明映射模块的工作流程。例如某用户访问地址:
http://promotion.xxx.com/hotel/2014/1111.html
。
- Nginx作为负载均衡,接受用户请求,并将请求转发到某个Tomcat实例上。
- Tomcat 通过查询本地缓存,得到物理地址,并将物理地址写入Response Header中,其key为:
X-Accel-Redirect
。 - Nginx获取到Response Header中包含
X-Accel-Redirect
,读取其中的value,并再次将请求分发到fastdfs-nginx-module
上。 fastdfs-nginx-module
返回数据给Nginx,用户接收到文件流,整体流程结束。
流程图
部署说明和关键配置
要实现如上的系统结构,在系统部署和配置上需要满足如下的条件:
- Nginx作为前端负载均衡
- Tomcat(或其他任意后端Server)部署映射处理程序
- Fastdfs Tracker和Storage服务器集群
- Nginx转发规则需要配置两个,一是fastdfs group路径,二是除此之外的所有路径。
Nginx转发规则配置如下:
转发规则1
转发规则2
upstream配置
还是以上文中的请求示例:
路径/hotel/2014/1111.html
会首先被规则2转发到映射处理程序,然后写入Response Header后,X-Accel-Redirect
的value为:/group1/M00/AA/BB/asldkjfj89oip9.html
,Nginx读取到该值,并由规则1继续完成处理。
X-Accel-Redirect是在Nginx内部处理,所以在用户端浏览器是看不到该header,不会暴露出文件的真实地址,浏览器也不会做302跳转,是在一次请求中完成。
总结
通过上述系统实现,映射模块具备如下的特点:
- 结构简单、轻量级
- 拥有基本上接近于静态文件服务器的性能
Tomcat
无IO压力- 易于部署和扩展
文件存储系统整体结构图
最后附上本系统的整体结构图,方便做更全面的了解。