1 背景
1.1 为什么需要分布式文件服务
1.1.1 单机时代
初创时期由于时间紧迫,在各种资源有限的情况下,通常就直接在项目目录下建立静态文件夹,用于用户存放项目中的文件资源。如果按不同类型再细分,可以在项目目录下再建立不同的子目录来区分。例如:resources\static\file、resources\static\iamge等。
.优点:这样做比较便利,项目直接引用就行,实现起来也简单,无需任何复杂技术,保存数据库记录和访问起来也很方便。
.缺点:如果只是后台系统的使用一般也不会有什么问题,但是作为一个前端网站使用的话就会存在弊端。一方面,文件和代码耦合在一起,文件越多存放越混乱;另一方面,如果流量比较大,静态文件访问会占据一定的资源,影响正常业务进行,不利于网站快速发展。
1.1.2 独立文件服务器
随着公司业务不断发展,将代码和文件放在同一服务器的弊端就会越来越明显。为了解决上面的问题引入独立图片服务器,工作流程如下:项目上传文件时,首先通过ftp或者ssh将文件上传到图片服务器的某个目录下,再通过ngnix或者apache来访问此目录下的文件,返回一个独立域名的图片URL地址,前端使用文件时就通过这个URL地址读取。
.优点:图片访问是很消耗服务器资源的(因为会涉及到操作系统的上下文切换和磁盘I/O操作),分离出来后,Web/App服务器可以更专注发挥动态处理的能力;独立存储,更方便做扩容、容灾和数据迁移;方便做图片访问请求的负载均衡,方便应用各种缓存策略(HTTP Header、Proxy Cache等),也更加方便迁移到CDN。
.缺点:单机存在性能瓶颈,容灾、垂直扩展性稍差
1.1.3 分布式文件系统
通过独立文件服务器可以解决一些问题,如果某天存储文件的那台服务突然down了怎么办?可能你会说,定时将文件系统备份,这台down机的时候,迅速切换到另一台就OK了,但是这样处理需要人工来干预。另外,当存储的文件超过100T的时候怎么办?单台服务器的性能问题?这个时候我们就应该考虑分布式文件系统了。
业务继续发展,单台服务器存储和响应也很快到达了瓶颈,新的业务需要文件访问具有高响应性、高可用性来支持系统。分布式文件系统,一般分为三块内容来配合,服务的存储、访问的仲裁系统,文件存储系统,文件的容灾系统来构成,仲裁系统相当于文件服务器的大脑,根据一定的算法来决定文件存储的位置,文件存储系统负责保存文件,容灾系统负责文件系统和自己的相互备份。
.优点:扩展能力: 毫无疑问,扩展能力是一个分布式文件系统最重要的特点;高可用性: 在分布式文件系统中,高可用性包含两层,一是整个文件系统的可用性,二是数据的完整和一致性;弹性存储: 可以根据业务需要灵活地增加或缩减数据存储以及增删存储池中的资源,而不需要中断系统运行
.缺点:系统复杂度稍高,需要更多服务器
1.2 什么是FastDFS
FastDFS是一个开源的轻量级分布式文件系统。它解决了大数据量存储和负载均衡等问题。特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务,如相册网站、视频网站等等。在UC基于FastDFS开发向用户提供了:网盘,社区,广告和应用下载等业务的存储服务。
FastDFS是一款开源的轻量级分布式文件系统纯C实现,支持Linux、FreeBSD等UNIX系统类google FS,不是通用的文件系统,只能通过专有API访问,目前提供了C、Java和PHP API为互联网应用量身定做,解决大容量文件存储问题,追求高性能和高扩展性FastDFS可以看做是基于文件的key value pair存储系统,称作分布式文件存储服务更为合适。
FastDFS特性:
.文件不分块存储,上传的文件和OS文件系统中的文件一一对应
.支持相同内容的文件只保存一份,节约磁盘空间
.下载文件支持HTTP协议,可以使用内置Web Server,也可以和其他Web Server配合使用
.支持在线扩容
.支持主从文件
.存储服务器上可以保存文件属性(meta-data)V2.0网络通信采用libevent,支持大并发访问,整体性能更好
开源地址:https://github.com/happyfish100/fastdfs
2 系统架构
FastDFS服务端有三个角色:跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)。
.tracker server:跟踪服务器,主要做调度工作,起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。相比GFS中的master更为精简,不记录文件索引信息,占用的内存量很少。
Tracker是FastDFS的协调者,负责管理所有的storage server和group,每个storage在启动后会连接Tracker,告知自己所属的group等信息,并保持周期性的心跳,tracker根据storage的心跳信息,建立group==>[storage server list]的映射表。
Tracker需要管理的元信息很少,会全部存储在内存中;另外tracker上的元信息都是由storage汇报的信息生成的,本身不需要持久化任何数据,这样使得tracker非常容易扩展,直接增加tracker机器即可扩展为tracker cluster来服务,cluster里每个tracker之间是完全对等的,所有的tracker都接受stroage的心跳信息,生成元数据信息来提供读写服务。
.storage server:存储服务器(又称:存储节点或数据服务器),文件和文件属性(meta data)都保存到存储服务器上。Storage server直接利用OS的文件系统调用管理文件。
Storage server(后简称storage)以组(卷,group或volume)为单位组织,一个group内包含多台storage机器,数据互为备份,存储空间以group内容量最小的storage为准,所以建议group内的多个storage尽量配置相同,以免造成存储空间的浪费。
以group为单位组织存储能方便的进行应用隔离、负载均衡、副本数定制(group内storage server数量即为该group的副本数),比如将不同应用数据存到不同的group就能隔离应用数据,同时还可根据应用的访问特性来将应用分配到不同的group来做负载均衡;缺点是group的容量受单机存储容量的限制,同时当group内有机器坏掉时,数据恢复只能依赖group内地其他机器,使得恢复时间会很长。
group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别挂载在/data/disk1-/data/disk10,则可将这10个目录都配置为storage的数据存储目录。
storage接受到写文件请求时,会根据配置好的规则(后面会介绍),选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在storage第一次启动时,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。
.client:客户端,作为业务请求的发起方,通过专有接口,使用TCP/IP协议与跟踪器服务器或存储节点进行数据交互。FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。
.group :组, 也可称为卷。 同组内服务器上的文件是完全相同的 ,同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server上进行 。
.meta data :文件相关属性,键值对( Key Value Pair) 方式,如:width=1024,heigth=768 。
2.1 Tracker集群
FastDFS集群中的Tracker server可以有多台,Trackerserver之间是相互平等关系同时提供服务,Trackerserver不存在单点故障。客户端请求Trackerserver采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。
2.2 Storage集群
为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷由一台或多台存储服务器组成,卷内的Storage server之间是平等关系,不同卷的Storageserver之间不会相互通信,同卷内的Storageserver之间会相互连接进行文件同步,从而保证同组内每个storage上的文件完全一致的。一个卷的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。卷中的多台存储服务器起到了冗余备份和负载均衡的作用
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
采用分组存储方式的好处是灵活、可控性较强。比如上传文件时,可以由客户端直接指定上传到的组也可以由tracker进行调度选择。一个分组的存储服务器访问压力较大时,可以在该组增加存储服务器来扩充服务能力(纵向扩容)。当系统容量不足时,可以增加组来扩充存储容量(横向扩容)。
2.3 Storage状态收集
Storage server会连接集群中所有的Tracker server,定时向他们报告自己的状态,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。
2.4 FastDFS的上传过程
FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。
Storage Server会定期的向Tracker Server发送自己的存储信息。当Tracker Server Cluster中的Tracker Server不止一个时,各个Tracker之间的关系是对等的,所以客户端上传时可以选择任意一个Tracker。
当Tracker收到客户端上传文件的请求时,会为该文件分配一个可以存储文件的group,当选定了group后就要决定给客户端分配group中的哪一个storage server。当分配好storage server后,客户端向storage发送写文件请求,storage将会为文件分配一个数据存储目录。然后为文件分配一个fileid,最后根据以上的信息生成文件名存储文件。
客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。
.组名:文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存。
.虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。
.数据两级目录:storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
.文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
2.5 FastDFS的文件同步
写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。
每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。
storage的同步进度会作为元数据的一部分汇报到tracker上,tracke在选择读storage的时候会以同步进度作为参考。
2.6 FastDFS的文件下载
客户端uploadfile成功后,会拿到一个storage生成的文件名,接下来客户端根据这个文件名即可访问到该文件。
跟upload file一样,在downloadfile时客户端可以选择任意tracker server。tracker发送download请求给某个tracker,必须带上文件名信息,tracke从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读请求。tracker根据请求的文件路径即文件ID 来快速定义文件。
比如请求下边的文件:
group1/M00/02/44/Swtdssdsdfsdf.txt
1.通过组名tracker能够很快的定位到客户端需要访问的存储服务器组是group1,并选择合适的存储服务器提供客户端访问。
2.存储服务器根据“文件存储虚拟磁盘路径”和“数据文件两级目录”可以很快定位到文件所在目录,并根据文件名找到客户端需要访问的文件。
3 安装配置
下面我们在单台机器上安装FastDFS,操作系统是64位的CentOS7。
名称 |
说明 |
centos |
7.x |
libfatscommon |
FastDFS分离出的一些公用函数包 |
FastDFS |
FastDFS本体 |
fastdfs-nginx-module |
FastDFS和nginx的关联模块 |
nginx |
nginx1.15.4 |
3.1 安装GCC
FastDFS是由C语言开发的,所以首先我们先安装C/C++的一个编译器:GCC
[root@node5-vm10 ~]# yum -y install gcc-c++ #验证GCC [root@node5-vm10 ~]# whereis gcc gcc: /usr/bin/gcc /usr/lib/gcc /usr/libexec/gcc /usr/share/man/man1/gcc.1.gz
3.2 安装libevent
事件通知库libevent也是需要提前安装的,这个库是由C语言开发的,具有轻量级、开源的、高性能的特点。
[root@node5-vm10 ~]# yum -y install libevent
3.3 安装libfastcommon
libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS运行所需要的一些基础库。
下载地址:https://github.com/happyfish100/libfastcommon/releases 选择合适的版本进行安装
#下载 [root@node5-vm10 ~]# cd /usr/local/src [root@node5-vm10 src]# wget -O libfastcommon-1.0.43.tar.gz https://codeload.github.com/happyfish100/libfastcommon/tar.gz/V1.0.43 #解压 [root@node5-vm10 src]# tar -zxvf libfastcommon-1.0.43.tar.gz #编译安装 [root@node5-vm10 src]# cd libfastcommon-1.0.43 [root@node5-vm10 libfastcommon-1.0.43]# ./make.sh [root@node5-vm10 libfastcommon-1.0.43]# ./make.sh install
3.4 安装FastDFS
下载地址:https://github.com/happyfish100/fastdfs/releases 选择合适的版本,当前最新release版本是6.06
#切换目录 [root@node5-vm10 libfastcommon-1.0.43]# cd /usr/local/src/ #下载 [root@node5-vm10 src]# wget -O fastdfs-6.06.tar.gz https://codeload.github.com/happyfish100/fastdfs/tar.gz/V6.06 #解压 [root@node5-vm10 src]# tar -zxvf fastdfs-6.06.tar.gz #安装 [root@node5-vm10 src]# cd fastdfs-6.06 [root@node5-vm10 fastdfs-6.06]# ./make.sh [root@node5-vm10 fastdfs-6.06]# ./make.sh install
默认安装方式安装后的相应文件与目录
A、服务脚本:
/etc/init.d/fdfs_storaged /etc/init.d/fdfs_trackerd
B、配置文件(这三个是作者给的样例配置文件)
/etc/fdfs/client.conf.sample /etc/fdfs/storage.conf.sample /etc/fdfs/tracker.conf.sample
C、命令工具在 /usr/bin/ 目录下:
fdfs_appender_test fdfs_appender_test1 fdfs_append_file fdfs_crc32 fdfs_delete_file fdfs_download_file fdfs_file_info fdfs_monitor fdfs_regenerate_filename fdfs_storaged fdfs_test fdfs_test1 fdfs_trackerd fdfs_upload_appender fdfs_upload_file
D、服务启动命令在:/usr/local/src/fastdfs-6.06
restart.sh setup.sh stop.sh
3.5 安装fastdfs-nginx-module
我们在使用FastDFS部署一个分布式文件系统的时候,通过FastDFS的客户端API来进行文件的上传、下载、删除等操作。同时通过FastDFS的HTTP服务器来提供HTTP服务。但是FastDFS的HTTP服务较为简单,无法提供负载均衡等高性能的服务,所以FastDFS的开发者(淘宝的架构师余庆)为我们提供了Nginx上使用的FastDFS模块(也可以叫FastDFS的Nginx模块)。
FastDFS 通过 Tracker 服务器,将文件放在 Storage 服务器存储, 但是集群环境下同组存储服务器之间需要进行文件复制, 有同步延迟的问题。假设 Tracker 服务器将文件上传到了 storage-server-1,上传成功后文件 ID已经返回给客户端。此时 FastDFS 存储集群机制会将这个文件同步到同组存储storage-server-2,在文件还没有复制完成的情况下,客户端如果用这个文件 ID 在 storage-server-2 上取文件,就会出现文件无法访问的错误。而 fastdfs-nginx-module 可以重定向文件链接到源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误。
[root@node5-vm10 fdfs]# cd /usr/local/src [root@node5-vm10 src]# git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1 [root@node5-vm10 src]# cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs [root@node5-vm10 src]# cp /usr/local/src/fastdfs-6.06/conf/http.conf /etc/fdfs/ [root@node5-vm10 src]# cp /usr/local/src/fastdfs-6.06/conf/mime.types /etc/fdfs/
3.5 安装Nginx
安装nginx的主要目的是做负载均衡及实现高可用。tracker集群环境下,需要在每个Tracker上安装Nginx, 如果只有一台tracker服务器,可以不配置Nginx。
Storage服务器安装Nginx
cd /usr/local/src #下载nginx压缩包 wget http://nginx.org/download/nginx-1.15.4.tar.gz #解压 tar -zxvf nginx-1.15.4.tar.gz cd nginx-1.15.4/ #添加fastdfs-nginx-module模块 ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ #编译安装 make && make install
配置Nginx:
vim /etc/fdfs/mod_fastdfs.conf #需要修改的内容如下 tracker_server=172.17.0.115:22122 #tracker服务器IP和端口 url_have_group_name=true base_path=/home/fastdfs/storage store_path0=/home/fastdfs/storage/base #配置nginx.config vim /usr/local/nginx/conf/nginx.conf #添加如下配置 server { listen 8188; ## 该端口为storage.conf中的http.server_port相同 server_name localhost; location ~/group[0-9]/ { ngx_fastdfs_module; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
启动Nginx:
/usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx -t /usr/local/nginx/sbin/nginx -s reload
3.6 配置FastDFS Tracker
3.5.1 配置Tracker
复制创建tracker.conf
[root@node5-vm10 fastdfs-6.06]# cd /etc/fdfs [root@node5-vm10 fdfs]# ll total 32 -rw-r--r--. 1 root root 1909 Apr 3 11:11 client.conf.sample -rw-r--r--. 1 root root 10246 Apr 3 11:11 storage.conf.sample -rw-r--r--. 1 root root 620 Apr 3 11:11 storage_ids.conf.sample -rw-r--r--. 1 root root 9138 Apr 3 11:11 tracker.conf.sample [root@node5-vm10 fdfs]# cp tracker.conf.sample tracker.conf
修改配置文件:
[root@node5-vm10 fdfs]# vim tracker.conf # HTTP port on this tracker server # 修改端口 http.server_port = 8180 # the base path to store data and log files base_path = /home/fastdfs/tracker
注意文件夹要手工创建好:
[root@node5-vm10 fdfs]# mkdir -p /home/fastdfs/tracker
3.5.2 启动与关闭
使用以下任一命令启动Tracker服务:
[root@node5-vm10 fdfs]# /etc/init.d/fdfs_trackerd start Reloading systemd: [ OK ] Starting fdfs_trackerd (via systemctl): [ OK ] # 或 [root@node5-vm10 fdfs]# service fdfs_trackerd start Starting fdfs_trackerd (via systemctl): [ OK ] # 或 [root@node5-vm10 fdfs]# systemctl start fdfs_trackerd
查看 FastDFS Tracker 是否已成功启动:
#初次成功启动后会在 /fdfsdfs/tracker/ (配置的base_path)下创建 data、logs 两个目录。 [root@node5-vm10 fdfs]# cd /fastdfs/tracker/ [root@node5-vm10 tracker]# ll total 0 drwxr-xr-x. 2 root root 58 Apr 3 11:28 data drwxr-xr-x. 2 root root 25 Apr 3 11:28 logs [root@node5-vm10 tracker]# systemctl status fdfs_trackerd ● fdfs_trackerd.service - LSB: FastDFS tracker server Loaded: loaded (/etc/rc.d/init.d/fdfs_trackerd; bad; vendor preset: disabled) Active: active (running) since Fri 2020-04-03 11:28:11 CST; 1min 8s ago Docs: man:systemd-sysv-generator(8) Process: 26724 ExecStart=/etc/rc.d/init.d/fdfs_trackerd start (code=exited, status=0/SUCCESS) Memory: 4.4M CGroup: /system.slice/fdfs_trackerd.service └─26727 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf Apr 03 11:28:09 node5-vm10.xxzx systemd[1]: Starting LSB: FastDFS tracker server... Apr 03 11:28:09 node5-vm10.xxzx fdfs_trackerd[26724]: Starting FastDFS tracker server: Apr 03 11:28:11 node5-vm10.xxzx systemd[1]: Started LSB: FastDFS tracker server.
使用以下任一命令关闭Tracker服务
service fdfs_trackerd stop 或 systemctl stop fdfs_trackerd 或 /etc/init.d/fdfs_trackerd stop
设置开机启动:
chkconfig fdfs_trackerd on 或 systemctl enable fdfs_trackerd.service 或者: vim /etc/rc.d/rc.local /etc/init.d/fdfs_trackerd start #加入配置
Tracker服务启动成功后,会在base_path下创建data、logs两个目录。目录结构如下:
${base_path} |__data | |__storage_groups.dat:存储分组信息 | |__storage_servers.dat:存储服务器列表 |__logs | |__trackerd.log: tracker server 日志文件
3.6 配置FastDFS Storage
3.6.1 配置Storage
进入 /etc/fdfs 目录,复制 FastDFS 存储器样例配置文件 storage.conf.sample,并重命名为 storage.conf
[root@node5-vm10 ~]# cd /etc/fdfs/ [root@node5-vm10 fdfs]# cp storage.conf.sample storage.conf [root@node5-vm10 fdfs]# vim storage.conf
修改以下配置信息,其他默认即可
# Storage 数据和日志目录地址(根目录必须存在,子目录会自动生成) # 这里不是上传的文件存放的地址 base_path = /home/fastdfs/storage # 逐一配置 store_path_count 个路径,索引号基于 0。 # 如果不配置 store_path0,那它就和 base_path 对应的路径一样。 store_path0 = /home/fastdfs/storage/base # FastDFS 存储文件时,采用了两级目录。这里配置存放文件的目录个数。 # 如果本参数只为 N(如: 256),那么 storage server 在初次运行时,会在 store_path 下自动创建 N * N 个存放文件的子目录。 subdir_count_per_path=256 # tracker_server 的列表 ,会主动连接 tracker_server # 有多个 tracker server 时,每个 tracker server 写一行 tracker_server = 172.17.0.115:22122 #访问端口 默认8888 http.server_port = 8188
创建Storage基础数据目录,对应base_path目录
# 对应base_path [root@node5-vm10 fdfs]# mkdir -p /home/fastdfs/storage # 这是配置的store_path0路径,有多个要创建多个 mkdir -p /home/fastdfs/storage/base
3.6.2 启动与关闭
启动Storage前确保Tracker是启动的,可以用以下任一方式启动Storage:
/etc/init.d/fdfs_storaged start 或 service fdfs_storaged start 或 systemctl start fdfs_storaged
查看 Storage 是否成功启动:
[root@node5-vm10 ~]# netstat -unltp|grep 23000 tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 28737/fdfs_storaged [root@node5-vm10 ~]# systemctl status fdfs_storaged ● fdfs_storaged.service - LSB: FastDFS storage server Loaded: loaded (/etc/rc.d/init.d/fdfs_storaged; bad; vendor preset: disabled) Active: active (running) since Fri 2020-04-03 11:59:31 CST; 39min ago Docs: man:systemd-sysv-generator(8) Process: 28716 ExecStop=/etc/rc.d/init.d/fdfs_storaged stop (code=exited, status=2) Process: 28734 ExecStart=/etc/rc.d/init.d/fdfs_storaged start (code=exited, status=0/SUCCESS) Memory: 66.9M CGroup: /system.slice/fdfs_storaged.service └─28737 /usr/bin/fdfs_storaged /etc/fdfs/storage.conf Apr 03 11:59:31 node5-vm10.xxzx systemd[1]: Starting LSB: FastDFS storage server... Apr 03 11:59:31 node5-vm10.xxzx systemd[1]: Started LSB: FastDFS storage server. Apr 03 11:59:31 node5-vm10.xxzx fdfs_storaged[28734]: Starting FastDFS storage server:
使用以下任一命令关闭Storage:
.service fdfs_storaged stop .systemctl stop fdfs_storaged ./etc/init.d/ fdfs_storaged stop
查看Storage和Tracker是否在通信:
[root@node5-vm10 ~]# /usr/bin/fdfs_monitor /etc/fdfs/storage.conf [2020-04-03 12:41:17] DEBUG - base_path=/fastdfs/storage, connect_timeout=5, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=1, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 server_count=1, server_index=0 tracker server is 172.17.0.115:22122 group count: 1 Group 1: group name = group1 disk total space = 196,011 MB disk free space = 29,774 MB ...
使用以下任一命令设置 Storage 开机启动:
.chkconfig fdfs_storaged on .systemctl enable fdfs_storaged.service
vim /etc/rc.d/rc.local 加入配置: /etc/init.d/fdfs_storaged start
Storage 目录:
Storage 启动成功后,在base_path 下创建了data、logs目录,记录着 Storage Server 的信息。
在 store_path0/data 目录下,创建了N*N个子目录:
[root@node5-vm10 ~]# ls /fastdfs/storage/data/ 00 07 0E 15 1C 23 2A 31 38 3F 46 4D 54 5B 62 69 70 77 7E 85 8C 93 9A A1 A8 AF B6 BD C4 CB D2 D9 E0 E7 EE F5 FC 01 08 0F 16 1D 24 2B 32 39 40 47 4E 55 5C 63 6A 71 78 7F 86 8D 94 9B A2 A9 B0 B7 BE C5 CC D3 DA E1 E8 EF F6 FD 02 09 10 17 1E 25 2C 33 3A 41 48 4F 56 5D 64 6B 72 79 80 87 8E 95 9C A3 AA B1 B8 BF C6 CD D4 DB E2 E9 F0 F7 FE 03 0A 11 18 1F 26 2D 34 3B 42 49 50 57 5E 65 6C 73 7A 81 88 8F 96 9D A4 AB B2 B9 C0 C7 CE D5 DC E3 EA F1 F8 FF 04 0B 12 19 20 27 2E 35 3C 43 4A 51 58 5F 66 6D 74 7B 82 89 90 97 9E A5 AC B3 BA C1 C8 CF D6 DD E4 EB F2 F9 05 0C 13 1A 21 28 2F 36 3D 44 4B 52 59 60 67 6E 75 7C 83 8A 91 98 9F A6 AD B4 BB C2 C9 D0 D7 DE E5 EC F3 FA 06 0D 14 1B 22 29 30 37 3E 45 4C 53 5A 61 68 6F 76 7D 84 8B 92 99 A0 A7 AE B5 BC C3 CA D1 D8 DF E6 ED F4 FB
3.7 文件测试
修改客户端配置:
[root@node5-vm10 ~]# cd /etc/fdfs [root@node5-vm10 fdfs]# cp client.conf.sample client.conf [root@node5-vm10 fdfs]# mkdir -p /home/fastdfs/client [root@node5-vm10 fdfs]# vim client.conf base_path = /home/fastdfs/client tracker_server = 172.17.0.115:22122 http.tracker_server_port = 8180
上传测试:
[root@node5-vm10 fdfs]# /usr/bin/fdfs_upload_file /etc/fdfs/client.conf /mnt/test.txt group1/M00/00/00/rBEAc16Hf5iAPXaNAAAAGWIeu9w946.txt
返回的文件ID由group、存储目录、二级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。上边示例中:
.组名:group1
.磁盘:M00
.存储目录:00
.二级子目录:00
.fileid: rBEAc16Hf5iAPXaNAAAAGWIeu9w946
.文件后缀: .txt
下载测试:
经过Nginx服务配置后,我们可以通过以下路径下载文件:
http://172.17.0.115:8188/group1/M00/00/00/rBEAc16Hf5iAPXaNAAAAGWIeu9w946.txt
3.8 FastDFS命令
.fdfs_upload_file:
Usage: fdfs_upload_file [storage_ip:port][store_path_index]
作用: 用于上传文件,用法为 fdfs_upload_file + 配置文件 + 文件
.fdfs_download_file
Usage: fdfs_download_file [local_filename][ ]
用于下载文件,用法为 fdfs_download_file + 配置文件 + 文件
.fdfs_file_info
Usage: fdfs_file_info
用于查看文件信息,用法为 fdfs_file_info + 配置文件 + 文件
.fdfs_delete_file
Usage: fdfs_delete_file
用于删除文件,用法为 fdfs_delete_file + 配置文件 + 文件
.fdfs_monitor
Usage: fdfs_monitor [-h ][list|delete|set_trunk_server [storage_id]]
用于查看集群信息,用法为 fdfs_monitor + 配置文件
[root@node5-vm10 ~]# fdfs_monitor /etc/fdfs/storage.conf
4 SpringBoot整合
4.1 操作步骤
1.配置FastDFS执行环境
2.文件上传配置
3.整合Swagger2测试接口
4.2 项目依赖
<!-- FastDFS依赖 --> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.26.5</version> </dependency> <!-- Swagger2 核心依赖 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
4.3 客户端开发
4.3.1 FastDFS配置
fdfs: # 链接超时 connect-timeout: 60 # 读取时间 so-timeout: 60 # 生成缩略图参数 thumb-image: width: 150 height: 150 tracker-list: 172.17.0.115:22122
4.3.2 FastDFS配置类
@Configuration @Import(FdfsClientConfig.class) // 避免Jmx重复注册bean @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) public class DFSConfig { }
4.3.3 文件工具类
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.service.FastFileStorageClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @Component public class FileDfsUtil { private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class); @Resource private FastFileStorageClient storageClient ; /** * 上传文件 */ public String upload(MultipartFile multipartFile) throws Exception{ String originalFilename = multipartFile.getOriginalFilename(). substring(multipartFile.getOriginalFilename(). lastIndexOf(".") + 1); StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage( multipartFile.getInputStream(), multipartFile.getSize(),originalFilename , null); return storePath.getFullPath() ; } /** * 删除文件 */ public void deleteFile(String fileUrl) { if (StringUtils.isEmpty(fileUrl)) { LOGGER.info("fileUrl == >>文件路径为空..."); return; } try { StorePath storePath = StorePath.parseFromUrl(fileUrl); storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); } catch (Exception e) { LOGGER.info(e.getMessage()); } } }
4.3.4 文件上传配置
spring: application: name: fdfs-demo jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss servlet: multipart: max-file-size: 100MB max-request-size: 100MB enabled: true
4.3.5 配置Swagger2
配置类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; /** * Swagger 配置文件 */ @Configuration public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.itheima.fdfs.demo")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("SpringBoot利用Swagger构建API文档") .description("Fast DFS接口") .version("version 1.0") .build(); } }
启动类:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableSwagger2 @SpringBootApplication public class FdfsDemoApplication { public static void main(String[] args) { SpringApplication.run(FdfsDemoApplication.class, args); } }
4.3.6 API接口
import com.itheima.fdfs.demo.common.FileDfsUtil; import io.swagger.annotations.ApiOperation; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; @RestController public class FileController { @Resource private FileDfsUtil fileDfsUtil ; /** * http://localhost:8081/swagger-ui.html */ @ApiOperation(value="上传文件", notes="测试FastDFS文件上传") @RequestMapping(value = "/uploadFile",headers="content-type=multipart/form-data", method = RequestMethod.POST) public ResponseEntity<String> uploadFile (@RequestParam("file") MultipartFile file){ String result ; try{ String path = fileDfsUtil.upload(file) ; if (!StringUtils.isEmpty(path)){ result = path ; } else { result = "上传失败" ; } } catch (Exception e){ e.printStackTrace() ; result = "服务异常" ; } return ResponseEntity.ok(result); } /** * 文件删除 */ @RequestMapping(value = "/deleteByPath", method = RequestMethod.GET) public ResponseEntity<String> deleteByPath (){ String filePathName = "group1/M00/00/00/rBEAc16Hf5iAPXaNAAAAGWIeu9w946.txt" ; fileDfsUtil.deleteFile(filePathName); return ResponseEntity.ok("SUCCESS") ; } }
4.4 接口演示
访问页面:http://172.17.0.115:8081/fdfs-demo/swagger-ui.html
别忘了开放端口:防火墙,22122 23000