FastDFS-6.0.6

1 简介

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

FastDFS对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载、文件删除)等,解决了大容量文件存储的问题,特别适合以文件为载体的在线服务,如相册网站、文档网站、图片网站、视频网站等等。

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

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

客户端通常指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端,FastDFS提供专有API访问,目前提供了C、Java和PHP几种编程语言的API,用来访问FastDFS文件系统。

1.1 框架分析

服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage),客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载,Storage server会连接集群中所有的Tracker server,定时向他们报告自己的状态,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。
在这里插入图片描述
Tracker

跟踪器(tracker)主要做调度工作 (类似于NameServer),在内存中记录集群中存储节点storage的状态信息,会根据策略找到相应的存储节点Storage,是前端Client和后端存储节点storage的枢纽。因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。

FastDFS集群中的Tracker server可以有多台,Tracker server之间是相互平等关系同时提供服务,Tracker server不存在单点故障。客户端请求Tracker server采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。

Storage

存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。

Storage集群采用了分组存储方式。storage集群由一个或多个组构成,集群存储总容量为集群中所有组的存储容量之和。一个组由一台或多台存储服务器组成,组内的Storage server之间是平等关系,不同组的Storage server之间不会相互通信,同组内的Storage server之间会相互连接进行文件同步,从而保证同组内每个storage上的文件完全一致的。一个组的存储容量为该组内的存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。

采用分组存储方式的好处是灵活、可控性较强。比如上传文件时,可以由客户端直接指定上传到的组也可以由tracker进行调度选择。一个分组的存储服务器访问压力较大时,可以在该组增加存储服务器来扩充服务能力(纵向扩容)。当系统容量不足时,可以增加组来扩充存储容量(横向扩容)。

1.2 文件管理流程

上传
客户端上传文件后存储服务器将返回文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

比如:group0/M00/01/01/123.jpg

组名:文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存。

虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。

数据两级目录:storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件,从00到FF共1024个,每个目录下又存在从00到FF共1024个文件夹,共存在两级。

文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
在这里插入图片描述
下载

tracker根据请求的文件信息来快速定位文件。

通过组名tracker能够很快的定位到客户端需要访问的存储服务器组,并选择合适的存储服务器提供客户端访问。
存储服务器根据“文件存储虚拟磁盘路径”和“数据文件两级目录”可以很快定位到文件所在目录,并根据文件名找到客户端需要访问的文件。
在这里插入图片描述

2 安装

2.1 安装环境

依赖:
yum install gcc
yum install libevent
yum install libevent-devel
创建工作目录:
mkdir -p /opt/fastdfs
mkdir -p /opt/fastdfs/libfastcommon

2.2 安装libfastcommon 库

下载地址:
https://github.com/happyfish100/libfastcommon
或者
https://download.csdn.net/download/zhuocailing3390/80476522

下载源码包
将下载的libfastcommon-1.0.43.tar并且拷贝到服务的/opt/fastdfs/libfastcommon目录下

cd /opt/fastdfs/libfastcommon
tar -zxvf libfastcommon-1.0.43.tar.gz

编译脚本

cd /opt/fastdfs/libfastcommon/libfastcommon-1.0.43
./make.sh
./make.sh install

2.3 安装fastDFS
从https://download.csdn.net/download/zhuocailing3390/80476522下载fastdfs-6.06.tar.gz安装包,然后拷贝到服务的/opt/fastdfs目录下
解压目录

cd /opt/fastdfs
tar -zxvf fastdfs-6.06.tar.gz

编译脚本

cd opt/fastdfs/fastdfs-6.06
./make.sh
./make.sh install

拷贝配置

将astdfs-6.06/conf下的http.conf、mime.types拷贝到 /etc/fdfs/)下
cd /opt/fastdfs/fastdfs-6.06/conf
cp http.conf /etc/fdfs/
cp mime.types /etc/fdfs/

验证
所有编译出来的文件存放在/usr/bin目录下:
ll /usr/bin/fdfs*

所有配置文件存放在/etc/fdfs目录下()
ll /etc/fdfs/
在这里插入图片描述

3 fastDFS配置

服务器和防火墙需要开启:22122与23000端口

3.1 修改文件名称

将/etc/fdfs目录下的所有带有.sample的后缀去掉

mv tracker.conf.sample tracker.conf
mv storage.conf.sample storage.conf
mv storage_ids.conf.sample storage_ids.conf
mv client.conf.sample client.conf
在这里插入图片描述

3.2 配置tracker

创建tracker服务器文件存放路径,用于存储tracker的数据文件和日志文件等

mkdir /data/fastdfs/tracker -p
修改配置指向路径
vim /etc/fdfs/tracker.conf
修改路径
base_path=/data/fastdfs/tracker

3.3 配置storage

创建storage服务器的文件目录,及文件储存目录

mkdir /data/fastdfs/storage -p
mkdir /data/fastdfs/storage/files -p

修改配置
vim /etc/fdfs/storage.conf

#storage存储数据目录
base_path=/data/fastdfs/storage
#真正存放文件的目录,可以指定多个,则store_path_count数量也需要修改
store_path0=/data/fastdfs/storage/files
#注册当前存储节点的tracker地址,默认为22122
tracker_server=111.12.35.67:22122

3.4 启动与停止

本地搭建在一台服务器上完成,如果资源充足并且为了实现高可用,可以在不同服务器上配置tracker与storage`并且分别进行启动。

tracker操作:

启动
fdfs_trackerd /etc/fdfs/tracker.conf start
重启
fdfs_trackerd /etc/fdfs/tracker.conf restart
停止
fdfs_trackerd /etc/fdfs/tracker.conf stop

storage操作:

启动
fdfs_storaged /etc/fdfs/storage.conf start
重启
fdfs_storaged /etc/fdfs/storage.conf restart
停止
fdfs_storaged /etc/fdfs/storage.conf stop

查看启动情况:

ps -ef|grep fdfs

#查看storage是否已经注册到了tracker下
fdfs_monitor /etc/fdfs/storage.conf
在这里插入图片描述
注意:首次启动成功后,会在storate配置的store_path0下(/data/fastdfs/storage/files)创建data文件夹,并且创建储存文件目录,共256个。

4 本机客户端测试

4.1 client配置

创建client目录、修改client.conf配置

#创建目录
mkdir /data/fastdfs/client -p

#修改配置
vim /etc/fdfs/client.conf

配置如下:
base_path=/data/fastdfs/client
tracker_server=111.12.35.67:22122

4.2 上传测试

在root目录下创建123.txt,上传命令:fdfs_test /etc/fdfs/client.conf upload /root/123.txt

创建123.txt并且写入任意内容
vim /root/123.txt

本地上传:
fdfs_test /etc/fdfs/client.conf upload /root/123.txt

在这里插入图片描述
可以看到文件储存在base_path0配置的目录下,虚拟数据目录00/00下,查看情况如下:

cd /data/fastdfs/storage/files/data/00/00

注意:文件上传会保存两份在服务器,一份从文件一份主文件

在这里插入图片描述

5 搭建http服务

5.1 配置环境库

5.2 编译nginx-module

下载地址:
https://github.com/happyfish100/fastdfs-nginx-module/releases
或者
https://download.csdn.net/download/zhuocailing3390/80476522
将下载的fastdfs-nginx-module-1.22.tar.gz包,拷贝到服务器的/opt/fastdfs目录下

解压模块:
tar -zxvf fastdfs-nginx-module-1.22.tar.gz

编译模块:
nginx添加第三方包的路径为:

–add-module=/opt/fastdfs/fastdfs-nginx-module-1.22/src

如果是首次配置nginx,参考《Nginx安装、配置》,并且在编译时指定–add-module;
如果已经安装过nginx,参考《Nginx二次编译—增加模块》,并且通过–add-module加入第三方模块;

5.3 配置fastdfs

拷贝mod_fastdfs.conf:
cp /opt/fastdfs/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf
/etc/fdfs
修改mod_fastdfs.conf:
vim /etc/fdfs/mod_fastdfs.conf

内容如下:
tracker_server=111.12.35.67:22122
#storage存储数据目录
base_path=/data/fastdfs/storage
#真正存放文件的目录,可以指定多个,则store_path_count数量也需要修改
store_path0=/data/fastdfs/storage/files
url_have_group_name=true

5.4 配置nginx

加入模块如下:

#拦截请求路径中包含 /group[1-9]/M0[0-9] 的请求
location ~ /group[1-9]/M0[0-9] {
#指令是扩展模块提供的,根据这个指令找到FastDFS,然后找到Tracker,最终找到Stroager
ngx_fastdfs_module;
}

5.5 测试

将nginx重新启动,重启fastDFS

重启tracker
fdfs_trackerd /etc/fdfs/tracker.conf restart
重启storage
fdfs_storaged /etc/fdfs/storage.conf restart
重启nginx
/usr/local/nginx/sbin/nginx -s reload

在上述4、本机客户端测试中,模拟文件了上传,比如地址为:http://111.12.35.67/group1/M00/00/00/og5zEmIJGg6ASH30AAAAERl-vyM286.txt

如果能够成功访问返回地址,及搭建服务成功

6 整合SpringBoot

6.1 引入pom

<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.27.2</version>
</dependency>

6.2 配置Bean

@Configuration
// 导入FastDFS-Client组件
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) 
public class FastDfsConfig {
}

6.3 配置yaml

分布式文件系统FDFS配置
fdfs:
soTimeout: 1500 #socket连接超时时长
connectTimeout: 600 #连接tracker服务器超时时长
thumbImage: #缩略图生成参数,可选
width: 150
height: 150
trackerList: #TrackerList参数,支持多个,我这里只有一个,如果有多个在下方加- x.x.x.x:port
- 111.12.35.67:22122

6.4 创建FileDfsUtil

封装一个统一的FileDfsUtil工具类,包含文件上传、删除的操作,代码如下:

@Component
public class FileDfsUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class);

    @Resource
    private FastFileStorageClient storageClient;

    /**
     * 上传文件指定分组名称
     */
    public String uploadAndGroupName(MultipartFile multipartFile, String groupName) throws Exception {
        //如果分布为空的话,进行默认上传
        if (groupName == null) {
            return upload(multipartFile);
        }
        //自定义分组名称
        try {
            String fileExName = getFileExName(multipartFile);
            StorePath storePath = storageClient.uploadFile(groupName, multipartFile.getInputStream(),
                    multipartFile.getSize(), fileExName);
            return storePath.getFullPath();
        } catch (Exception e) {
            throw new RuntimeException("上传失败");
        }
    }

    /**
     * 上传文件
     */
    public String upload(MultipartFile multipartFile) {
        try {
            String fileExName = getFileExName(multipartFile);
            StorePath storePath = this.storageClient.uploadFile(
                    multipartFile.getInputStream(),
                    multipartFile.getSize(), fileExName, null);
            return storePath.getFullPath();
        } catch (Exception e) {
            throw new RuntimeException("上传失败:" + e.getMessage());
        }
    }

    /**
     * 上传缩略图
     */
    public String uploadThumbImage(MultipartFile multipartFile) {

        try {
            String fileExName = getFileExName(multipartFile);
            fileExName = fileExName.toLowerCase();
            if (!"jpg".equals(fileExName) && !"png".equals(fileExName)) {
                return "图片格式错误";
            }
            StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(
                    multipartFile.getInputStream(),
                    multipartFile.getSize(), fileExName, null);
            return storePath.getFullPath();
        } catch (Exception e) {
            throw new RuntimeException("上传失败");
        }
    }
    /**
     * 删除文件
     */
    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());
            throw new RuntimeException("删除失败失败");
        }
    }

    private String getFileExName(MultipartFile multipartFile) {
        return StringUtils.substringAfter(multipartFile.getOriginalFilename(), ".");
    }
}

6.5 整合使用

Controller代码如下:

@RestController
public class FileController {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class);

    @Resource
    private FileDfsUtil fileDfsUtil;

    @Value("${fdfs.thumbImage.width}")
    private Integer width;

    @Value("${fdfs.thumbImage.height}")
    private Integer height;

    /**
     * 文件上传
     */
    @PostMapping(value = "/uploadFile", headers = "content-type=multipart/form-data")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
        long s1 = System.currentTimeMillis();
        String path = fileDfsUtil.upload(file);
        long s2 = System.currentTimeMillis();
        LOGGER.info("耗时:" + (s2 - s1));
        //实际开发中,应该将path信息,存入数据库,和file进行关联,用户下载时只需要传入fileId即可
        //返回的路径,是不存在http地址,group1/M00/00/00/1312312312.txt,具体的前缀由前端拼接
        return ResponseEntity.ok(path);
    }

    /**
     * 上传缩略图
     * 一般不建议使用fastDFS缩略图,实际开发中,应该自定义尺寸后再进行上传
     */
    @PostMapping(value = "/uploadThumbImage", headers = "content-type=multipart/form-data")
    public ResponseEntity<List<String>> uploadThumbImage(@RequestParam("file") MultipartFile file) {
        String path = fileDfsUtil.uploadThumbImage(file);
        //上传缩略图以后,服务器会生成两个文件,一个是原图,一个缩略图,并且缩略图的名称为原图+"_width*height"
        //group1/M00/00/00/1123.jpg与group1/M00/00/00/1123_150x150.jpg
        //设置缩略图路径
        String prePath = StringUtils.substringBeforeLast(path, ".");
        String suffix = StringUtils.substringAfterLast(path, ".");
        String imagePath = prePath + "_" + width + "x" + height + "." + suffix;
        List<String> paths = new ArrayList<>();
        paths.add(path);
        paths.add(imagePath);
        return ResponseEntity.ok(paths);
    }

    /**
     * 文件删除
     */
    @DeleteMapping
    public ResponseEntity<String> deleteByPath(String path) {
        long s1 = System.currentTimeMillis();
        fileDfsUtil.deleteFile(path);
        long s2 = System.currentTimeMillis();
        LOGGER.info("耗时:" + (s2 - s1));
        return ResponseEntity.ok("SUCCESS");
    }
}

7 token链验证下载

默认情况下,我们通过nginx访问,FastDFS的文件地址,就可以进行下载,但是为了数据的安全性,FastDFS提供了token机制,在进行下载时,会进行验证,验证通过了才能进行下载。
在进行验证时,先通过接口传入文件的地址,比如:group1/M00/00/00/og5zEmIJ3syANzOZAAN3V3RVe_M236.png,然后fasfdfs会返回一个带token的正式地址,比如:group1/M00/00/00/og5zEmIJ3syANzOZAAN3V3RVe_M236.png?token=c10624b0358abbed66d3a1a52fb6cbc4&ts=1644814838,然后通过带token地址即可访问资源。

7.1 修改http.conf

配置:

vim /etc/fdfs/http.conf

#内容:
#开启token
http.anti_steal.check_token = true
#密钥
http.anti_steal.secret_key = FastDFS1234567890
#验证失败后加载内容,需要上传一个404.jpg的文件
http.anti_steal.token_check_fail = /etc/fdfs/404.jpg

重启:

重启tracker
fdfs_trackerd /etc/fdfs/tracker.conf restart
重启storage
fdfs_storaged /etc/fdfs/storage.conf restart
重启nginx
/usr/local/nginx/sbin/nginx -s reload

7.2 Java配置

引入pom

<dependency>
   <groupId>net.oschina.zcx7878</groupId>
   <artifactId>fastdfs-client-java</artifactId>
   <version>1.27.0.0</version>
</dependency>

代码实现

// 此处直接传递文件路径,实际中应该是通过文件Id在数据库找到文件路径
public ResponseEntity downloadFile(String filePath) {
try {
String path = StorePath.parseFromUrl(filePath).getPath();
int ts = (int) (System.currentTimeMillis() / 1000);
//实际中也可以自己实现逻辑,不需要引入 fastdfs-client-java 包
//secretKey与http.conf中的http.anti_steal.secret_key一致
String token = ProtoCommon.getToken(path, ts, secretKey);
return ResponseEntity.ok(filePath + “?token=” + token + “&ts=” + ts);
} catch (Exception e) {
e.printStackTrace();
}

 下载地址:
https://github.com/happyfish100?spm=a2c6h.12873639.0.0.13f94369HwkEAY
http://nginx.org/en/download.html?spm=a2c6h.12873639.0.0.13f94369GynrMG

sed -i "s#enforcing#disabled#g"  /etc/sysconfig/selinux 
echo $?

wget -c "https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz" \
-O fastdfs-6.06.tar.gz
wget -c "https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz" \
-O libfastcommon-1.0.43.tar.gz
wget -c "https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz" \
-O fastdfs-nginx-module-1.22.tar.gz
wget -c http://nginx.org/download/nginx-1.17.7.tar.gz


路径 /usr/local/fast下解压软件
tar -zxvf fastdfs-6.06.tar.gz
tar -zxvf fastdfs-nginx-module-1.22.tar.gz
tar -zxvf libfastcommon-1.0.43.tar.gz
tar -zxvf nginx-1.17.7.tar.gz

yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel


(1)编译安装 libfastcommon
cd /usr/local/fast/libfastcommon-1.0.43
./make.sh && ./make.sh install
检查
ls /usr/lib64|grep libfastcommon
ls /usr/lib|grep libfastcommon
出现libfastcommon.so即成功

#创建目录
mkdir -p /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、进入解压后的目录
cd /usr/local/fast/fastdfs-6.06    
./make.sh && ./make.sh install
3、检查
ls /usr/bin|grep fdfs

4、启用配置文件
cd /etc/fdfs/
cp storage.conf.sample storage.conf
cp client.conf.sample client.conf
cp tracker.conf.sample tracker.conf
mkdir -p /fastdfs/tracker

5、修改 tracker.conf 文件
vim /etc/fdfs/tracker.conf
base_path = /fastdfs/tracker

6、启动 tracker 服务
/etc/init.d/fdfs_trackerd start
service fdfs_trackerd start
systemctl start fdfs_trackerd

7、检查服务是否启动
ps -ef|grep fdfs

8、修改 storage.conf 文件

vim /etc/fdfs/storage.conf
base_path = /fastdfs/storage   //数据和日志
store_path0 = /fastdfs/storage  //图片
tracker_server = 192.168.119.10:22122
http.server_port = 80

9、创建目录
mkdir -p /fastdfs/storage

10、启动 storage 服务
/etc/init.d/fdfs_storaged start

检查fastdfs的tracker与storage是否整合成功
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf

11、设置开机启动
vi /etc/rc.d/rc.local
加入配置
/etc/init.d/fdfs_trackerd start
/etc/init.d/fdfs_storaged start

12、编辑 client.conf 文件
vim /etc/fdfs/client.conf 
修改
base_path=/fastdfs/tracker
tracker_server=192.168.119.10:22122

上传图片  /usr/bin/fdfs_upload_file /etc/fdfs/client.conf boy.jpg
下载图片  /usr/bin/fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKh3CmBukR2AT5OiAADCIn60HdY293.jpg
上传图片信息  /usr/bin/fdfs_file_info  /etc/fdfs/client.conf group1/M00/00/00/wKh3CmBukR2AT5OiAADCIn60HdY293.jpg
查看存储节点状态  /usr/bin/fdfs_monitor /etc/fdfs/client.conf
2.3、安装 nginx 和 fastdfs-nginx-module
yum -y install pcre pcre-devel
cd /usr/local/fast/nginx-1.17.7
./configure --prefix=/usr/local/nginx --with-http_stub_status_module
cd /usr/local/fast/fastdfs-nginx-module-1.22/src
vim config
6、将config文件中的/usr/local替换成/usr
:%s+/usr/local+/usr
:%s/usr\/local/usr

添加fastdfs-nginx-module
./configure --add-module=/usr/local/fast/fastdfs-nginx-module-1.22/src/
make && make install

10、复制并修改fastdfs-ngin-module中的配置文件
cp /usr/local/fast/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs/
vim /etc/fdfs/mod_fastdfs.conf

修改配置

connect_timeout=10
40行  tracker_server=192.168.119.10:22122
53行  url_have_group_name = true
62行  store_path0=/fastdfs/storage

11、进入fastdfd源码conf目录
cd /usr/local/fast/fastdfs-6.06/conf/

12、将http.conf,mime.types两个文件拷贝到/etc/fdfs/目录下
cp http.conf mime.types /etc/fdfs/

13、创建一个软连接,在/fastdfs/storage文件存储目录下创建软连接,将其链接到实际存放数据 的目录
ln -s /fastdfs/storage/data/ /fastdfs/storage/data/M00

14、编辑 nginx 配置
vim /usr/local/nginx/conf/nginx.conf

server {
    listen       80;
    server_name  192.168.119.10;
    location ~/group([0-9])/M00 {
            root  /fastdfs/storage/data;
            ngx_fastdfs_module;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37705525/article/details/125400348
今日推荐