Linux - 搭建FastDFS分布式文件系统
1. FastDFS简介
说明:FastDFS简介部分的理论知识全部来自于博主bojiangzhou的 《用FastDFS一步步搭建文件管理系统》,在此感谢博主的无私分享。当然最最要感谢的是余庆老师,分享了这么好用的分布式文件系统。
1.1 FastDFS简介
FastDFS是一个开源的高效分布式文件系统(DFS)。他主要功能包括:文件存储、文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(4KB ~ 500MB)为载体的在线服务。
FastDFS系统有三个角色:跟踪服务器(Tracker Server),存储服务器(Storage Server),客户端(Client).
-
- Tracker Server:跟踪服务器,主要做调度工作,起到负载均衡的作用;负载管理所有的Group和Group中的Storage Server,每个Storage Server在启动后会连接Tracker Server,高中自己所属的Group等信息,并保持周期心跳。
- Storage Server:存储服务器,主要提供存储和备份服务;以Group为单位,每个Group内可以有一到多台Storage Server,Group内的多台Storage Server数据互为备份,Group的存储容量取决于该Group内最小Storage Server的容量。
- Client:客户端,上传下载数据的服务器,也就是我们项目所部署的服务器。
1.2 FastDFS存储策略
为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
1.3 FastDFS上传过程
FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。
Storage Server会定期的向Tracker Server发送自己的存储信息。当Tracker Server Cluster中的Tracker Server不止一个时,各个Tracker Server之间的关系是对等的,所以客户端上传时可以选择任意一个Tracker Server。
当Tracker Server收到客户端上传文件的请求时,会为该文件分配一个可以存储文件的Group,当选定了Group后就要决定给客户端分配Group中的哪一个Storage Server。当分配好Storage Server后,客户端向Storage Server发送写文件请求,Storage Server将会为文件分配一个数据存储目录。然后为文件分配一个fileid,最后根据以上的信息生成文件名存储文件。
1.4 FastDFS文件同步
写文件时,客户端将文件写至Group内一个Storage Server即认为写文件成功,Storage Server写完文件后,会由后台线程将文件同步至同Group内其他的Storage Server。
每个Storage Server写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,Storage Server会记录向Group内其他Storage Server同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有Server的时钟保持同步。
Storage Server的同步进度会作为元数据的一部分汇报到Tracker Server上,Tracke Server在选择读Storage Server的时候会以同步进度作为参考。
1.5 FastDFS的文件下载
客户端uploadfile成功后,会拿到一个Storage Server生成的文件名,接下来客户端根据这个文件名即可访问到该文件。
跟upload file一样,在downloadfile时客户端可以选择任意Tracker Server。客户端发送download请求给某个Tracker Server,必须带上文件名信息,Tracke Server从文件名中解析出文件的Group、大小、创建时间等信息,然后为该请求选择一个Storage Server用来服务读请求。
2. FastDFS安装环境及拓扑图
如图所示,使用FastDFS搭建一套分布式存储的文件系统,由于新版的FastDFS未提供Http功能,我们使用Nginx及fastdfs-nginx-module模块实现通过Http访问存储的内容。Tracker Server上的Nginx通过Keepalived实现高可用。上传功能使用Python客户端实现。
2.1 FastDFS分布式存储拓扑图
2.2 FastDFS安装环境
2.2.1 按照拓扑图所示准备服务器
- 两台Tracker Server提高系统可用性,避免单点故障,同时对于客户端API,起到负载均衡的作用。
- 每两台Storage Server组成一个Group。总共3个组。
- API客户端使用Python客户端。
- Storage Server上安装Nginx,提供Http功能。
- Tracker Server上安装Nginx和fastdfs-nginx-module模块,与Tracker Server配合,为客户端提供Http功能,为后端Storage Server上的Nginx提供反向代理和负载均衡的作用。
2.2.2 安装环境说明
Tracker Server、Storage Server服务由安装包fastdfs提供,而fastdfs安装包依赖于libfastcommon提供的库,Python客户端依赖于fastdfs和libfastcommon提供的库,所以所有服务器均需安装libfastcommon和fastdfs。
Storage Server服务器上的Nginx只需提供Web服务功能,用于访问该服务器上存储的文件即可,不需安装fastdfs-nginx-module模块,当然安装也没问题。
Tracker Server服务器上的Nginx需要安装fastdfs-nginx-module模块,Tracker Server可以根据路径获取文件所在的Storage Server的IP,Nginx需与Tracker Server交互获取该IP。
2.2.3 同步服务器时间,所有服务器启用ntp或chrony服务同步时间
ntp或chrony服务的安装配置参考我的另外一篇博客:Linux - CentOS7上的时间同步
2.2.4 下载安装包
下载地址:
FastDFS项目地址:https://github.com/happyfish100
fastdfs下载地址:https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz
libfastcommon下载地址:https://github.com/happyfish100/libfastcommon/archive/V1.0.39.tar.gz
fastdfs-nginx-module下载地址:https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz
Nginx下载地址:http://nginx.org/download/nginx-1.12.2.tar.gz
Python客户端下载地址:https://github.com/zhubiaook/fastdfs-python-client/archive/fdfs-python-client-v0.1.tar.gz
下载安装包
# 创建一个目录,存储下载的安装包 $ sudo mkdir /usr/local/src/fdfs $ cd /usr/local/src/fdfs # 下载fastdfs: sudo wget https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz # 下载libfastcommon sudo wget https://github.com/happyfish100/libfastcommon/archive/V1.0.39.tar.gz # 下载fastdfs-nginx-module sudo wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz # 下载Nginx sudo wget http://nginx.org/download/nginx-1.12.2.tar.gz # 下载Python客户端 sudo wget https://github.com/zhubiaook/fastdfs-python-client/archive/fdfs-python-client-v0.1.tar.gz
3. FastDFS分布式存储搭建
3.1 所有服务器安装libfastcommon、fastdfs
安装libfastcommon
# 安装依赖库 sudo yum -y install gcc-c++ # 解压 sudo tar -xf V1.0.39.tar.gz cd libfastcommon-1.0.39/ # 编译 sudo ./make.sh # 安装 sudo ./make.sh install
安装 fastdfs
# 解压 sudo tar -xf V5.11.tar.gz cd fastdfs-5.11 # 编译 sudo ./make.sh # 安装 sudo ./make.sh install
3.2 配置跟踪器(Tracker Server)
两台Tracker Server的配置一样。
创建Tracker Server数据、日志文件存储路径
sudo mkdir /data/fdfs/tracker -p
修改配置文件
# 进入配置文件目录 $ cd /etc/fdfs # 复制配置文件 $ sudo cp tracker.conf.sample tracker.conf # 修改配置文件中的以下两行 $ sudo vim tracker.conf base_path=/data/fdfs/tracker http.server_port=80
启动Tracker Server服务
# 方法1: $ sudo service fdfs_trackerd start # 方法2: $ sudo /etc/init.d/fdfs_trackerd start
查看监听的端口是否启动
$ sudo netstat -tunlp | grep 22122 tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 12178/fdfs_trackerd
3.3 配置存储节点(Storage Server)
所有Storage Server的配置一样
创建Storage Server数据、日志文件存储路径
# data目录存储日志文件,file目录存储上传的文件目录
$ sudo mkdir /data/fdfs/{storage,file} -p
修改配置文件
# 进入配置文件目录 $ cd /etc/fdfs # 复制配置文件 $ sudo cp storage.conf.sample storage.conf # 修改配置文件以下几行内容 $ sudo vim storage.conf
group_name=group1 #此处填写所在的组,比如group1, group2, group3 ... base_path=/data/fdfs/storage store_path0=/data/fdfs/file tracker_server=192.168.0.201 tracker_server=192.168.0.202 http.server_port=80
启动Storage Server服务
$ sudo service fdfs_storaged start
查看监听的端口
$ sudo netstat -tunlp | grep 2300 tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 12964/fdfs_storaged
测试Storage Server 与 Tracker Server 是否正常通信
[2018-10-12 15:49:28] DEBUG - base_path=/data/fdfs/storage, connect_timeout=30, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 server_count=2, server_index=0 tracker server is 192.168.0.201:22122 group count: 2 Group 1: group name = group1 disk total space = 97231 MB disk free space = 95790 MB trunk free space = 0 MB storage server count = 2 active server count = 2 storage server port = 23000 storage HTTP port = 80 store path count = 1 subdir count per path = 256 current write server index = 0 current trunk file id = 0 Storage 1: id = 192.168.0.203 ip_addr = 192.168.0.203 (192.168.0.203) ACTIVE ... Storage 2: id = 192.168.0.204 ip_addr = 192.168.0.204 (192.168.0.204) ACTIVE ... Group 2: group name = group2 disk total space = 0 MB disk free space = 0 MB trunk free space = 0 MB storage server count = 2 active server count = 0 storage server port = 23000 storage HTTP port = 80 store path count = 1 subdir count per path = 256 current write server index = 0 current trunk file id = 0 Storage 1: id = 192.168.0.205 ip_addr = 192.168.0.205 (192.168.0.205) OFFLINE ... Storage 2: id = 192.168.0.206 ip_addr = 192.168.0.206 (192.168.0.206) OFFLINE ...
3.4 上传、下载文件测试
到目前为止,可以使用FastDFS提供的客户端工具进行文件的上传、下载、删除等操作,在任意一台Tracker Server或Storage Server上都安装了这些工具,下面我们在其中一台Tracker Server上进行文件上传、下载的测试。
a. 配置客户端
$ cd /etc/fdfs/ $ sudo cp client.conf.sample client.conf
# 修改以下配置 $ sudo vim client.conf connect_timeout=30 base_path=/data/fdfs/client <=客户端日志存储路径 tracker_server=192.168.0.201:22122 tracker_server=192.168.0.202:22122 http.tracker_server_port=80
b. 上传文件
# 新建一个文件,然后将此文件上传到FastDFS中 $ echo 'Hello World' > ~/test.html # 上传文件 $ fdfs_upload_file /etc/fdfs/client.conf ~/test.html group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html
文件上传后,返回一个文件存储的路径 group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html ,路径由以下及部分组成
组名:group1
磁盘:M00
Storage Server上存储路径:00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html
c. 下载文件
$ fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html
3.5 安装配置存储节点(Storage Server)上的Nginx
a. 安装Nginx
安装Nginx,存储节点上的Nginx可以使用Yum安装,也可以自己编译安装
方法1:使用YUM安装
$ sudo yum -y install nginx
方法2:编译安装
# 安装依赖包 $ sudo yum -y install openssl-devel pcre-devel
# 创建系统用户nginx
$ useradd nginx -r # 解压Nginx $ sudo tar -xvf nginx-1.12.2.tar.gz $ cd nginx-1.12.2 # 执行./configure,生成Makefile文件 sudo ./configure \ --prefix=/usr/share/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib64/nginx/modules \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \--http-proxy-temp-path=/var/lib/nginx/tmp/proxy \ --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi \ --pid-path=/run/nginx.pid \ --lock-path=/run/lock/subsys/nginx \ --user=nginx \ --group=nginx \ --with-file-aio \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_stub_status_module \ --with-pcre \ --with-stream=dynamic \ --with-stream_ssl_module \ --with-debug \ --with-http_ssl_module # 编译 $ sudo make # 安装 $ sudo make install
b. 配置Nginx
$ vim /etc/nginx/conf.d/fdfs.conf server { listen 80; server_name localhost; location ~ ^/group[0-9]/M00/(.*) { alias /data/fdfs/file/data/$1; } }
c. 本机上访问文件(注意,访问的路径属于哪个组,就在哪个组下的Storage Server上测试)
$ curl http://127.0.0.1/group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html Hello World
3.6 安装配置跟踪器(Tracker Server)上的Nginx
跟踪器上的Nginx,需要增加 fastdfs-nginx-module模块,只能通过编译安装完成
a. 安装Nginx所需的依赖包
$ sudo yum -y install pcre-devel openssl-devel zlib-devel
b. 解压fastdfs-nginx-module模块,并修改配置文件,否则Nginx编译的时候会报错。
$ 解压 $ sudo tar -xvf V1.20.tar.gz # 修改配置文件 $ sudo vim fastdfs-nginx-module-1.20/src/config ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon" CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon"
c. 创建nginx用户
$ sudo useradd nginx -r
d. 安装Nginx
# 解压nginx $ sudo tar -xvf nginx-1.12.2.tar.gz # 进入nginx源码目录进行编译安装 $ cd nginx-1.12.2 # 执行configure $ sudo ./configure \ --prefix=/usr/share/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib64/nginx/modules \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \--pid-path=/run/nginx.pid \ --lock-path=/run/lock/subsys/nginx \ --user=nginx \ --group=nginx \ --with-file-aio \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_stub_status_module \ --with-pcre \ --with-stream=dynamic \ --with-stream_ssl_module \ --with-debug \ --with-http_ssl_module \ --add-module=../fastdfs-nginx-module-1.20/src # 编译 $ sudo make # 安装 $ sudo make install
e. 复制fastdfs-nginx-module-1.20中的配置文件到/etc/fdfs目录下,并进行修改
$ sudo cp fastdfs-nginx-module-1.20/src/mod_fastdfs.conf /etc/fdfs/ $ sudo vim /etc/fdfs/mod_fastdfs.conf # 连接超时时间 connect_timeout=10 # Tracker Server tracker_server=192.168.0.201:22122 tracker_server=192.168.0.202:22122 # StorageServer 默认端口 storage_server_port=23000 # 如果文件ID的uri中包含/group**,则要设置为true url_have_group_name = true
f. 复制fastdfs-5.11目录中的部分配置文件到/etc/fdfs目录下
$ cd fastdfs-5.11/conf/ $ sudo cp anti-steal.jpg http.conf mime.types /etc/fdfs/
g. 修改nginx配置文件
$ sudo vim /etc/nginx/conf.d/fdfs.conf server { listen 80; server_name file.zjqrkj.cn; location / { index index.html index.htm; root /data/fdfs/file/data; } location ~/group([0-9])/M00 { ngx_fastdfs_module; } error_page 500 502 503 504 /500.html; client_max_body_size 20M; keepalive_timeout 10; }
h. 访问测试
$ curl http://192.168.0.201/group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html Hello World $ curl http://192.168.0.202/group1/M00/00/00/wKgAy1vAVbKAB66QAAAADAsMGmk02.html Hello World
3.7 安装配置Keepalived,实现跟踪器上的Nginx高可用
VRRP ( Virtual Router Redundancy Protocol ) 是一种容错协议,它保证当主机的下一跳路由器出现故障,由另外一台路由器来代替出现故障的路由器进行工作,从而保证网络通信的可靠性。Keepalived 是Linux系统上VRRP协议的实现,Keepalived与Nginx反向代理服务器等配合使用,实现高可用。
我的另外一篇博客介绍了安装、配置过程,此处不再连篇累牍,参考:Keepalived+LVS/Nginx 实验
3.8 安装Python客户端
a. 安装python-devel
sudo yum -y install python-devel
b. 解压sudo tar -xvf fdfs-python-client-v0.1.tar.gz,并复制该目录下的fastdfspyclient到 fastdfs-5.11源码目录下的client文件夹中
# 解压 $ sudo tar -xvf fdfs-python-client-v0.1.tar.gz # 复制文件 $ sudo cp -ar fastdfs-python-client-fdfs-python-client-v0.1/fastdfspyclient fastdfs-5.11/client/
c. 进入fastdfspyclient目录下,执行make生成fdfspyclient.so文件
$ cd fastdfs-5.11/client/fastdfspyclient/ # 执行make $ sudo make
d. 此时可以将源码目录下的client目录复制到本机的其他目录,作为Python客户端。此处我们暂且复制到家目录下。
cp -ar /usr/local/src/fdfs/fastdfs-5.11/client ~/
e. 修改该目录下的客户端配置文件
$ sudo vim client/fastdfspyclient/client.conf # 日志存储路径 base_path=/data/fdfs/client # tracker server tracker_server=192.168.0.201:22122 tracker_server=192.168.0.202:22122
f. 创建客户端日志存储路径
$ sudo mkdir /data/fdfs/client
g. 测试,可以参照fastdfspyclient目录下的fdfstest.py进行模拟测试
# 创建测试文件 $ echo "Something so beautiful" > ~/test.html $ cd client/fastdfspyclient/ $ python Python 2.7.5 (default, Jul 13 2018, 13:06:57) >>> import fdfspyclient as fp >>> fp.fdfs_init('client.conf') [2018-10-12 18:21:41] DEBUG - base_path=/data/fdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 0 >>> result, groupname, remotefilename, fileurl = fp.fdfs_upload("/home/zhubiao/test.html", None) >>> result 0 >>> fileurl 'http://192.168.0.204/group1/M00/00/00/wKgAzFvAdciAKY4iAAAAF_Cudkk79.html'
4. 参考文档
[博客] 用FastDFS一步步搭建文件管理系统
[GitHub] 官网FastDFS托管仓库
[GitHub] FastDFS Python 客户端