FastDFS分布式文件系统

FastDFS分布式文件系统

一:分布式文件系统

分布式文件系统(Distributed File System)是一个软件/软件服务器,这个软件可以用来管理文件

但是这个软件管理的文件通常不是在一个服务器的节点上,而是在多个服务器的节点上,这些服务器节点通过网络相连构成了一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件管理系统来管理这些服务器上的文件。

常见的分布式文件系统有:FastDFS,GFS,HDFS,Lustre,Ceph,GridFS等等。

二:FastDFS简介

FastDFS是一个开源的轻量级分布式文件系统,为互联网应用量身定做,简单,灵活,高效,采用C语言开发,由阿里巴巴开发并开源

FastDFS主要对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题

特别适合以文件为载体的在线服务,如相册网站、视频网站等等。

FastDFS充分考虑了冗余备份、线性扩容等机制,并注重高可用,高性能等指标

使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务

github地址:https://github.com/happyfish100/fastdfs

FastDFS由跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)三个部分组成

主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。

在这里插入图片描述

三:FastDFS整体架构

在这里插入图片描述

FastDFS文件系统由两大部分构成,一个是客户端,一个是服务端。

客户端

客户端通常指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端

FastDFS提供专有API访问,目前提供了C、Java和PHP几种编程语言的API,用来访问FastDFS文件系统

服务端

由两个部分构成:一个是跟踪服务器(Tracker server),一个是存储服务器(Storage server)

客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载

  • Tracker server作用:
    • 负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server提供文件上传服务
    • Tracker Server负责管理所有的storage server和group
    • 每个storage在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。
    • 多个Tracker之间是对等关系,不存在单点故障
  • Storage server作用:
    • 文件存储,客户端上传的文件最终存储在Storage服务器上
    • Storage server没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。
    • Storage Server可以分为多个group组( 卷1、卷2、卷n ),每个组之间保存的文件是不同的。
    • 每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念

一个完整的FastDFS集群架构大概是这样的:

在这里插入图片描述

四:文件操作流程

1:文件上传流程

在这里插入图片描述

2:文件下载流程

在这里插入图片描述

3:文件删除流程

在这里插入图片描述

五:文件同步机制

同一组内的storage server之间是对等的,文件上传、删除等操作可以在任意一台storage server上进行

文件同步只在同组内的storage server之间进行,采用push方式,即源服务器同步给目标服务器【有个例外,就是新增加一台storage server时,由已有的一台storage server将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器】

源头数据才需要同步,备份数据不需要再次同步,否则就构成环路了

六:环境搭建演示

1:下载安装 libfastcommon

libfastcommon是从 FastDFS 和 FastDHT 中提取出来的公共 C 函数库,基础环境,安装即可

mkdir fastdfs
cd fastdfs/ # 新建一个文件夹,一会所有的包都存储到这里

下载或者上传安装libfastcommon

wget https://github.com/happyfish100/libfastcommon/archive/V1.0.7.tar.gz

因为FastDFS是使用c语言开发,需要先安装gcc环境,否则之后运行类库的 ./make.sh 会报错

yum -y install gcc
yum -y install gcc-c++

解压libfastcommon

tar -zxvf libfastcommonV1.0.7.tar.gz

解压后,会生成libfastcommon-1.0.7文件夹,里面有make.sh编译脚本。使用这个脚本进行编译和安装

./make.sh  # 编译
./make.sh install # 安装

libfastcommon.so 安装到了/usr/lib64/libfastcommon.so,而FastDFS主程序设置的lib目录是/usr/local/lib,所以需要创建软链接

ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so
ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so 

2:下载安装FastDFS

1:下载 -> 下载地址:https://sourceforge.net/projects/fastdfs/files/,我们会看到如下图所示界面

在这里插入图片描述

在这里插入图片描述

wget https://github.com/happyfish100/fastdfs/archive/V5.05.tar.gz

然后下载这个V5.05即可【可能国内的网络比较卡,可能需要翻墙】,下载完成之后上传到服务器的fastDFS文件夹下,然后进行解压缩

tar -zxvf FastDFS_v5.05.tar.gz 

解压缩之后,可以看到生成了FastDFS文件夹,里面有编译相关脚本:

$ ll
total 412
drwxr-xr-x. 10 8980 users    258 Dec  2  2014 FastDFS
-rw-r--r--.  1 root root  345400 Nov  9 14:39 FastDFS_v5.05.tar.gz
drwxrwxr-x.  3 root root     102 Nov  9 14:31 libfastcommon-1.0.7
-rw-r--r--.  1 root root   73148 Nov  9 14:30 libfastcommonV1.0.7.tar.gz

$ cd FastDFS/
$ ll
total 120
drwxr-xr-x. 3 8980 users  4096 Dec  2  2014 client
drwxr-xr-x. 2 8980 users   261 Dec  2  2014 common
drwxr-xr-x. 2 8980 users   146 Dec  2  2014 conf
-rw-r--r--. 1 8980 users 35067 Dec  2  2014 COPYING-3_0.txt
-rw-r--r--. 1 8980 users  2802 Dec  2  2014 fastdfs.spec
-rw-r--r--. 1 8980 users 31386 Dec  2  2014 HISTORY
drwxr-xr-x. 2 8980 users    48 Dec  2  2014 init.d
-rw-r--r--. 1 8980 users  7755 Dec  2  2014 INSTALL
-rwxr-xr-x. 1 8980 users  5813 Dec  2  2014 make.sh
drwxr-xr-x. 2 8980 users  4096 Dec  2  2014 php_client
-rw-r--r--. 1 8980 users  2380 Dec  2  2014 README.md
-rwxr-xr-x. 1 8980 users  1768 Dec  2  2014 restart.sh
-rwxr-xr-x. 1 8980 users  1680 Dec  2  2014 stop.sh
drwxr-xr-x. 4 8980 users  4096 Dec  2  2014 storage
drwxr-xr-x. 2 8980 users  4096 Dec  2  2014 test
drwxr-xr-x. 2 8980 users  4096 Dec  2  2014 tracker
[root@localhost FastDFS]#

执行编译、安装

./make.sh
./make.sh install

FastDFS默认服务脚本路径

/etc/init.d/fdfs_storaged # 存储
/etc/init.d/fdfs_trackerd # 调度

FastDFS相关配置文件示例

/etc/fdfs/client.conf.sample  # 客户端配置示例
/etc/fdfs/storage.conf.sample # 存储端配置示例
/etc/fdfs/tracker.conf.sample # 调度端配置示例

FastDFS默认的脚本安装后放在/usr/bin下面,但是FastDFS 服务脚本设置的 bin 目录是 /usr/local/bin

所以还是需要建立 /usr/bin/usr/local/bin 的软链接。

ln -s /usr/bin/fdfs_trackerd   /usr/local/bin
ln -s /usr/bin/fdfs_storaged   /usr/local/bin
ln -s /usr/bin/stop.sh         /usr/local/bin
ln -s /usr/bin/restart.sh      /usr/local/bin

3:配置tracker调度

编辑tracker.conf[vim tracker.conf],需要修改如下几个地方:

  • disabled=false -> 这个参数表示启用
  • port=22122 -> 这个参数指定了服务监听的端口号,这个注意在防火墙中开发,【如果是自己用着玩,可以直接关闭防火墙】
  • base_path=/fastdfs/tracker -> 指定调度tracker的base路径,这个注意需要mkdir /fastdfs/tracker
  • http.server_port=80 -> 这个参数指定了HTTP服务器监听的端口号。80端口是HTTP协议的默认端口

然后启动tracker,启动成功后,会在 /fastdfs/tracker (配置的base_path)下创建 data、logs 两个目录,如下所示:

/etc/init.d/fdfs_trackerd start
Reloading systemd:                                         [  OK  ]
Starting fdfs_trackerd (via systemctl):                    [  OK  ]

查看 FastDFS Tracker 是否已成功启动 ,22122端口正在被监听,则说明Tracker服务安装成功。

netstat -unltp | grep fdfs

设置Tracker开机启动

chkconfig fdfs_trackerd on

Tracker server目录及文件结构

Tracker服务启动成功后,会在base_path下创建data、logs两个目录。目录结构如下:

${base_path}
  |__data
  |   |__storage_groups.dat # 存储分组信息
  |   |__storage_servers.dat # 存储服务器列表
  |__logs
  |   |__trackerd.log: tracker server # 日志文件

4:配置storage存储

复制 storage.conf.sample,并重命名为 storage.conf

cp storage.conf.sample storage.conf

ll
total 36
-rw-r--r--. 1 root root 1461 Nov  9 14:42 client.conf.sample
-rw-r--r--. 1 root root 7829 Nov  9 15:41 storage.conf
-rw-r--r--. 1 root root 7829 Nov  9 14:42 storage.conf.sample
-rw-r--r--. 1 root root 7234 Nov  9 15:12 tracker.conf
-rw-r--r--. 1 root root 7102 Nov  9 14:42 tracker.conf.sample

编辑storage.conf,主要修改下面几个地方

  • disabled=false -> 表示该存储节点是启用的,即可以接收文件存储请求。如果设置为true,则节点会被禁用。
  • group_name=group1 -> 指定该存储节点所属的组名。在FastDFS中,文件通过组名和文件名进行唯一标识
  • port=23000 -> 指定存储节点监听的端口号,客户端和跟踪服务器(Tracker Server)通过此端口与存储节点进行通信
  • heart_beat_interval=30 -> 心跳包发送的时间间隔,单位为秒。存储节点会定期向跟踪服务器发送心跳包以维持连接状态
  • base_path=/fastdfs/storage -> 存储节点的基路径,用于存放日志文件等
  • store_path_count=1 -> 指定存储路径的个数。FastDFS支持一个节点配置多个存储路径,以提高存储效率和可靠性
  • store_path0=/fastdfs/file -> 具体的存储路径,用于存放实际文件。这里的0表示第一个存储路径
  • subdir_count_per_path=256 -> 每个存储路径下子目录的个数。FastDFS会在每个存储路径下创建多个子目录来存放文件,以提高文件访问性能
  • tracker_server=192.168.179.133:22122 -> 指定跟踪服务器的地址和端口
  • sync_start_time=00:00 -> 指定了文件同步的时间范围
  • sync_end_time=23:59 -> 指定了文件同步的时间范围
  • http.server_port=80 -> 这里指定了HTTP服务器监听的端口号为80

根据上面的配置修改,可能需要修改下面两个部分:

  • 创建Storage基础数据目录,对应base_path目录mkdir /fastdfs/storage & mkdir /fastdfs/file
  • 防火墙中打开存储器端口(默认的 23000),打开之后,别忘了重启防火墙service iptables restart

启动 Storage,启动Storage前确保Tracker是启动的

/etc/init.d/fdfs_storaged start
Starting fdfs_storaged (via systemctl):                    [  OK  ]

启动成功之后,会在 /fastdfs/storage 目录下创建 data、 logs 两个目录,同时可以使用命令查看是否启动成功

netstat -unltp | grep fdfs

设置storage开机自启动

chkconfig fdfs_storaged on

5:其他说明配置

查看Storage和Tracker是否在通信

/usr/bin/fdfs_monitor /etc/fdfs/storage.conf

在这里插入图片描述

Storage目录结构

同 Tracker,Storage 启动成功后,在base_path 下创建了data、logs目录,记录着 Storage Server 的信息。

在 store_path0 目录下,创建了N*N个子目录:

在这里插入图片描述

6:文件上传测试

复制Tracker客户端配置文件,并取名"client.conf"

cp client.conf.sample client.conf

修改client.conf,主要修改下面几个地方:

  • base_path=/fastdfs/client -> 指定基路径,注意创建mkdir /fastdfs/client
  • tracker_server=192.168.179.133:22122 -> 声明调度器的ip:port

进行上传测试

[root@localhost /]# 
[root@localhost /]# ll
total 36
lrwxrwxrwx.   1 root root     7 Sep 18  2019 bin -> usr/bin
dr-xr-xr-x.   5 root root  4096 Sep 18  2019 boot
drwxr-xr-x.  20 root root  3260 Nov  9 14:25 dev
drwxr-xr-x.   3 root root    80 Oct 10 15:12 elasticsearch
drwxr-xr-x.   3 root root    80 Oct 10 15:50 es
drwxr-xr-x. 135 root root  8192 Nov  9 14:42 etc
drwxr-xr-x.   8 root root   166 Nov  9 16:05 fastdfs
drwxr-xr-x.   4 root root    27 Oct 10 15:13 home
lrwxrwxrwx.   1 root root     7 Sep 18  2019 lib -> usr/lib
lrwxrwxrwx.   1 root root     9 Sep 18  2019 lib64 -> usr/lib64
drwxr-xr-x.   2 root root     6 Apr 11  2018 media
drwxr-xr-x.   2 root root     6 Apr 11  2018 mnt
drwxr-xr-x.   3 root root    16 Sep 18  2019 opt
dr-xr-xr-x. 211 root root     0 Nov  9 14:25 proc
dr-xr-x---.   5 root root   262 Nov  9 16:04 root
drwxr-xr-x.  38 root root  1220 Nov  9 14:30 run
lrwxrwxrwx.   1 root root     8 Sep 18  2019 sbin -> usr/sbin
drwxr-xr-x.   2 root root     6 Apr 11  2018 srv
dr-xr-xr-x.  13 root root     0 Nov  9 14:25 sys
-rw-r--r--.   1 root root 12637 Nov  9 16:13 timg.png
drwxrwxrwt.  30 root root  4096 Nov  9 16:05 tmp
drwxr-xr-x.  13 root root   155 Sep 18  2019 usr
drwxr-xr-x.  20 root root   282 Sep 18  2019 var
[root@localhost /]# /usr/bin/fdfs_upload_file /etc/fdfs/client.conf timg.png 
group1/M00/00/00/wKizhV-o-jiAQ08WAAAxXVoV3i4602.png # <------ 注意返回结构

可以看到,文件上传成功,返回文件ID号:group1/M00/00/00/wKizhV-o-jiAQ08WAAAxXVoV3i4602.png

返回的文件ID由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。

  • group1:组名
  • M00:磁盘
  • 00/00:目录
  • wKizhV-o-jiAQ08WAAAxXVoV3i4602.png:文件名 & 后缀

七:整合nginx

前面已经成功实现了文件上传到Storage中,但我们暂时还不能下载文件,需要安装Nginx作为服务器以支持Http方式访问文件

一个tracker对应多个storage,通过nginx对storage负载均衡[所以Nginx只需要安装到StorageServer所在的服务器即可,用于访问文件。]

在这里插入图片描述

1:安装nginx

安装gcc-c++[前面已经安装过了]、 PCRE pcre-devel、zlib、OpenSSL

yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-devel

下载nginx,以nginx-1.18.0.tar.gz为例。http://nginx.org/en/download.html

在这里插入图片描述

上传到服务器上之后,解压:

tar -zxvf nginx-1.18.0.tar.gz 

使用默认的配置

./configure 

编译,安装

[root@localhost nginx-1.18.0]# make
[root@localhost nginx-1.18.0]# make install

启动nginx

cd /usr/local/nginx/sbin/
./nginx 

ps -ef | grep nginx # 查看是否启动

防火墙中打开Nginx端口(默认的 80),修改完成之后,重启防火墙

2:测试访问文件

我们需要修改一下nginx.conf,增加下面的配置:

# 将 /group1/M00 映射到 /fastdfs/file/data
location /group1/M00 {
         alias /fastdfs/file/data; # 这个是上面storage中的具体的存储路径,用于存放实际文件的那个配置
}

修改完成之后,重启nginx:

/usr/local/nginx/sbin/nginx -s reload

重启完成之后,在浏览器访问之前上传的图片:http://xxx/group1/M00/00/00/wKizhV-o-jiAQ08WAAAxXVoV3i4602.png

3:整合fastdfs-nginx-module模块

前面已经通过安装Nginx实现了从浏览器访问FastDFS中的文件信息

在生产环境中,我们的存储服务storage一般都是有几台机器组成一个组,当上传一个文件后,同组存储服务器之间需要进行文件复制

此时可能存在同步延迟的问题。为了解决这个问题,FastDFS提供了 fastdfs-nginx-module的Nginx模块

fastdfs-nginx-module可以重定向文件链接到源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误

以1.16版本为例进行安装:【https://sourceforge.net/projects/fastdfs/files】

在这里插入图片描述

在这里插入图片描述

将fastdfs-nginx-module_v1.16.tar.gz上传到服务器后[/fastdfs下],解压操作

[root@localhost fastdfs]# tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
[root@localhost fastdfs]# ll
total 1448
drwxr-xr-x.  2 root root        6 Nov  9 16:05 client
drwxr-xr-x. 10 8980 users     258 Nov  9 14:42 FastDFS
drwxrwxr-x.  3  500   500      47 May  4  2014 fastdfs-nginx-module
-rw-r--r--.  1 root root    17510 Nov 16 15:49 fastdfs-nginx-module_v1.16.tar.gz
-rw-r--r--.  1 root root   345400 Nov  9 14:39 FastDFS_v5.05.tar.gz
drwxr-xr-x.  3 root root       18 Nov  9 15:52 file
drwxrwxr-x.  3 root root      102 Nov  9 14:31 libfastcommon-1.0.7
-rw-r--r--.  1 root root    73148 Nov  9 14:30 libfastcommonV1.0.7.tar.gz
drwxr-xr-x.  9 es   mysql     186 Nov  9 17:05 nginx-1.18.0
-rw-r--r--.  1 root root  1039530 Nov  9 17:03 nginx-1.18.0.tar.gz
drwxr-xr-x.  4 root root       30 Nov  9 15:52 storage
drwxr-xr-x.  4 root root       30 Nov  9 15:22 tracker

[root@localhost fastdfs]# cd fastdfs-nginx-module/
[root@localhost fastdfs-nginx-module]# ll
total 8
-rw-rw-r--. 1 500 500 2342 May  4  2014 HISTORY
-rw-rw-r--. 1 500 500 1733 May  4  2014 INSTALL
drwxrwxr-x. 2 500 500  109 May  4  2014 src

配置Nginx,在nginx中添加模块

# 首先我们停止nginx服务,然后进入解压包目录,然后添加模块:
[root@localhost nginx-1.18.0]# ./configure --add-module=/fastdfs/fastdfs-nginx-module/src

# 重新编译,安装
[root@localhost nginx-1.18.0]# make && make install

# 查看nginx模块
[root@localhost nginx-1.18.0]# /usr/local/nginx/sbin/nginx -V
...
configure arguments: --add-module=/fastdfs/fastdfs-nginx-module/src # <--- 如果发现这句表示添加成功

复制 fastdfs-nginx-module 源码中的配置文件到/etc/fdfs 目录

[root@localhost /]# cd fastdfs/fastdfs-nginx-module/
[root@localhost fastdfs-nginx-module]# cd src/
[root@localhost src]# ll
total 76
-rw-rw-r--. 1 500 500 33207 Aug 30  2013 common.c
-rw-rw-r--. 1 500 500  3479 Jan  3  2012 common.h
-rw-rw-r--. 1 500 500   447 Nov  4  2010 config
-rw-rw-r--. 1 500 500  3679 Mar 30  2013 mod_fastdfs.conf
-rw-rw-r--. 1 500 500 28542 May  4  2014 ngx_http_fastdfs_module.c
[root@localhost src]# cp mod_fastdfs.conf /etc/fdfs/
[root@localhost src]# 

修改mod_fastdfs.conf如下配置,其它默认:

  • connect_timeout=10
  • tracker_server=192.168.179.133:22122
  • url_have_group_name = true:如果文件ID的uri中包含/group**,则要设置为true;
  • store_path0=/fastdfs/file:Storage 配置的store_path0路径,必须和storage.conf中的一致;

复制 FastDFS 的部分配置文件到 /etc/fdfs 目录

[root@localhost /]# cd fastdfs/
[root@localhost fastdfs]# ll
total 1448
drwxr-xr-x.  2 root root        6 Nov  9 16:05 client
drwxr-xr-x. 10 8980 users     258 Nov  9 14:42 FastDFS
drwxrwxr-x.  3  500   500      47 May  4  2014 fastdfs-nginx-module
-rw-r--r--.  1 root root    17510 Nov 16 15:49 fastdfs-nginx-module_v1.16.tar.gz
-rw-r--r--.  1 root root   345400 Nov  9 14:39 FastDFS_v5.05.tar.gz
drwxr-xr-x.  3 root root       18 Nov  9 15:52 file
drwxrwxr-x.  3 root root      102 Nov  9 14:31 libfastcommon-1.0.7
-rw-r--r--.  1 root root    73148 Nov  9 14:30 libfastcommonV1.0.7.tar.gz
drwxr-xr-x.  9 es   mysql     186 Nov  9 17:05 nginx-1.18.0
-rw-r--r--.  1 root root  1039530 Nov  9 17:03 nginx-1.18.0.tar.gz
drwxr-xr-x.  4 root root       30 Nov  9 15:52 storage
drwxr-xr-x.  4 root root       30 Nov  9 15:22 tracker
[root@localhost fastdfs]# cd FastDFS/
[root@localhost FastDFS]# ll
total 124
drwxr-xr-x. 3 8980 users  4096 Nov  9 14:42 client
drwxr-xr-x. 2 8980 users  4096 Nov  9 14:41 common
drwxr-xr-x. 2 8980 users   146 Dec  2  2014 conf
-rw-r--r--. 1 8980 users 35067 Dec  2  2014 COPYING-3_0.txt
-rw-r--r--. 1 8980 users  2802 Dec  2  2014 fastdfs.spec
-rw-r--r--. 1 8980 users 31386 Dec  2  2014 HISTORY
drwxr-xr-x. 2 8980 users    48 Dec  2  2014 init.d
-rw-r--r--. 1 8980 users  7755 Dec  2  2014 INSTALL
-rwxr-xr-x. 1 8980 users  5813 Dec  2  2014 make.sh
drwxr-xr-x. 2 8980 users  4096 Dec  2  2014 php_client
-rw-r--r--. 1 8980 users  2380 Dec  2  2014 README.md
-rwxr-xr-x. 1 8980 users  1768 Dec  2  2014 restart.sh
-rwxr-xr-x. 1 8980 users  1680 Dec  2  2014 stop.sh
drwxr-xr-x. 4 8980 users  4096 Nov  9 14:42 storage
drwxr-xr-x. 2 8980 users  4096 Dec  2  2014 test
drwxr-xr-x. 2 8980 users  4096 Nov  9 14:42 tracker
[root@localhost FastDFS]# cd conf/
[root@localhost conf]# ll
total 84
-rw-r--r--. 1 8980 users 23981 Dec  2  2014 anti-steal.jpg
-rw-r--r--. 1 8980 users  1461 Dec  2  2014 client.conf
-rw-r--r--. 1 8980 users   858 Dec  2  2014 http.conf
-rw-r--r--. 1 8980 users 31172 Dec  2  2014 mime.types
-rw-r--r--. 1 8980 users  7829 Dec  2  2014 storage.conf
-rw-r--r--. 1 8980 users   105 Dec  2  2014 storage_ids.conf
-rw-r--r--. 1 8980 users  7102 Dec  2  2014 tracker.conf
[root@localhost conf]# cp anti-steal.jpg http.conf mime.types /etc/fdfs/

配置nginx,修改nginx.conf

[root@localhost fdfs]# cd /usr/local/nginx/
[root@localhost nginx]# ll
total 4
drwx------. 2 nobody root    6 Nov  9 17:07 client_body_temp
drwxr-xr-x. 2 root   root 4096 Nov  9 17:14 conf
drwx------. 2 nobody root    6 Nov  9 17:07 fastcgi_temp
drwxr-xr-x. 2 root   root   40 Nov  9 17:06 html
drwxr-xr-x. 2 root   root   41 Nov  9 17:30 logs
drwx------. 2 nobody root    6 Nov  9 17:07 proxy_temp
drwxr-xr-x. 2 root   root   36 Nov 16 16:09 sbin
drwx------. 2 nobody root    6 Nov  9 17:07 scgi_temp
drwx------. 2 nobody root    6 Nov  9 17:07 uwsgi_temp
[root@localhost nginx]# cd conf/
[root@localhost conf]# ll
total 68
-rw-r--r--. 1 root root 1077 Nov  9 17:06 fastcgi.conf
-rw-r--r--. 1 root root 1077 Nov 16 16:09 fastcgi.conf.default
-rw-r--r--. 1 root root 1007 Nov  9 17:06 fastcgi_params
-rw-r--r--. 1 root root 1007 Nov 16 16:09 fastcgi_params.default
-rw-r--r--. 1 root root 2837 Nov 16 16:09 koi-utf
-rw-r--r--. 1 root root 2223 Nov 16 16:09 koi-win
-rw-r--r--. 1 root root 5231 Nov  9 17:06 mime.types
-rw-r--r--. 1 root root 5231 Nov 16 16:09 mime.types.default
-rw-r--r--. 1 root root 2763 Nov  9 17:14 nginx.conf
-rw-r--r--. 1 root root 2656 Nov 16 16:09 nginx.conf.default
-rw-r--r--. 1 root root  636 Nov  9 17:06 scgi_params
-rw-r--r--. 1 root root  636 Nov 16 16:09 scgi_params.default
-rw-r--r--. 1 root root  664 Nov  9 17:06 uwsgi_params
-rw-r--r--. 1 root root  664 Nov 16 16:09 uwsgi_params.default
-rw-r--r--. 1 root root 3610 Nov 16 16:09 win-utf
[root@localhost conf]# vim nginx.conf
location ~/group([0-9])/M00 {
	ngx_fastdfs_module;
}
  • listen 80 端口值是要与 /etc/fdfs/storage.conf 中的 http.server_port=80 (前面改成80了)相对应。如果改成其它端口,则需要统一
  • location 的配置,如果有多个group则配置location ~/group([0-9])/M00 ,没有则不用配group。

启动nginx并进行测试

[root@localhost sbin]# ./nginx
ngx_http_fastdfs_set pid=10971

重新上传一张图片:

[root@localhost /]# 
[root@localhost /]# /usr/bin/fdfs_upload_file /etc/fdfs/client.conf timg.png 
group1/M00/00/00/wKizhV-yOiOAUrLTAAAxXVoV3i4802.png
[root@localhost /]# 

在地址栏访问:http://192.168.179.133/group1/M00/00/00/wKizhV-yOiOAUrLTAAAxXVoV3i4802.png。

如果能成功访问到图片,说明我们的配置没有问题。

八:客户端API实现文件上传下载

前面已经搭建好了FastDFS环境,在实际工作中,一般都是使用FastDFS客户端API来上传或者下载文件

fastDFS client是开源的,https://github.com/tobato/FastDFS_Client

在这里插入图片描述

首先,我们创建一个springboot项目,项目目录结构大体如下:

在这里插入图片描述

1:依赖和配置

引入FastDFS、Thymeleaf等依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- taobao fastdfs依赖 -->
<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.26.5</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>
server:
  port: 80
# 分布式文件系统FDFS配置
fdfs:
  soTimeout: 1500 #socket连接超时时长
  connectTimeout: 600 #连接tracker服务器超时时长
  reqHost: 192.168.179.133   #nginx访问地址
  reqPort: 80              #nginx访问端口
  thumbImage: #缩略图生成参数,可选
    width: 150
    height: 150
  trackerList: #TrackerList参数,支持多个,这里只有一个,如果有多个在下方加- x.x.x.x:port
    - 192.168.179.133:22122
    #- 192.168.179.134:22122
    #- 192.168.179.135:22122
spring:
  application:
    name: fastdfs-demo
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 20MB

2:配置FastDFS

import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;
 
@Configuration
@Import(FdfsClientConfig.class) // 导入FastDFS-Client组件
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) // 解决jmx重复注册bean的问题
public class CustomFastDFSConfiguration {
 
}

3:编写FastDFS操作文件的工具类

FastDFS上传、下载以及删除文件底层都是靠的FastFileStorageClient对象来对文件进行操作。

import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.FileOutputStream;
import java.io.IOException;
 
@Component
public class FastDFSClientUtils {
 
    private static Logger logger = LoggerFactory.getLogger(FastDFSClientUtils.class);
 
    @Autowired
    private FastFileStorageClient fastFileStorageClient;
 
    /**
     * 上传文件
     */
    public String uploadFile(MultipartFile multipartFile) throws Exception {
        // 拿到原始文件名
        String originalFilename = multipartFile.getOriginalFilename()
            .substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
        // fastFileStorageClient进行上传操作并且生成缩略图,注意参数:文件的流,文件大小,原始文件名称
        StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(
                multipartFile.getInputStream(),
                multipartFile.getSize(), originalFilename, null);
        // 拿到存储后的完整路径
        return storePath.getFullPath();
    }
 
    /**
     * 删除文件
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            logger.info("需要删除的文件路径为空......");
            return;
        }
        try {
            // 通过fileUrl解析出来storePath
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            // 调用fastFileStorageClient.deleteFile进行删除
            fastFileStorageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
    }
 
    /**
     * 下载文件
     */
    public byte[] downloadFile(String fileUrl) {
        // 拿到分组和路径从fileUrl中
        String group = fileUrl.substring(0, fileUrl.indexOf("/"));
        String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
        logger.info("下载文件的group: {},path: {}", group, path);
        // 声明一个DownloadByteArray
        DownloadByteArray downloadByteArray = new DownloadByteArray();
        // 调用downloadFile进行下载,返回文件的字节数组
        byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
        try {
            //将文件保存到d盘
            FileOutputStream fileOutputStream = new FileOutputStream("d:\\image.png");
            fileOutputStream.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }
 
}

4:控制层编写

import com.springboot.fastdfs.fastdfsdemo.utils.FastDFSClientUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
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.multipart.MultipartFile;
 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.Arrays;
 
@Controller
public class FastDFSController {
 
    private static final Logger logger = LoggerFactory.getLogger(FastDFSController.class);
 
    @Resource
    private FastDFSClientUtils fastDFSClientUtils;
 
    @GetMapping("/")
    public String index() {
        return "upload";
    }
 
    /**
     * 文件上传
     */
    @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 = fastDFSClientUtils.uploadFile(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(@RequestParam("filePathName") String filePathName) {
        if (StringUtils.isBlank(filePathName)) {
            logger.error("请传入需要删除的文件路径!");
            return ResponseEntity.ok("请传入需要删除的文件路径!");
        }
        fastDFSClientUtils.deleteFile(filePathName);
        return ResponseEntity.ok("文件删除成功!");
    }
 
    /**
     * 文件下载
     */
    @GetMapping("/downloadFile")
    public void downloadFile(@RequestParam("filePathName") String filePathName, HttpServletResponse response) {
        if (StringUtils.isBlank(filePathName)) {
            logger.error("请传入需要下载的文件路径!");
        } else {
            byte[] bytes = fastDFSClientUtils.downloadFile(filePathName);
            logger.info(Arrays.toString(bytes));
 
            //此处需要设置ISO8859-1,application/octet-stream为未知文件类型时使用
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            BufferedOutputStream output;
            try {
                output = new BufferedOutputStream(response.getOutputStream());
                response.setHeader("Content-Disposition", "attachment;filename=image.png");
                output.write(bytes);
                response.flushBuffer();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

5:随便编写一个upload.html

<!DOCTYPE html>
<html>
<body>
 
<h1>FastDFS 文件上传案例</h1>
 
<form method="POST" action="/uploadFile" enctype="multipart/form-data">
    <input type="file" name="file"/><br/><br/>
    <input type="submit" value="上传文件"/>
</form>
 
</body>
</html>

在启动项目之前,确保FastDFS环境都已经启动成功

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值