文章目录


1.简介

FastDFS是由国人余庆所开发,其项目地址:​​https://github.com/happyfish100​

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

FastDFS充分考虑了冗余备份、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务;

2.FastDFS架构

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

FastDFS的两个核心概念分别是:Tracker(跟踪器)、Storage(存储节点)

Tracker server作用是负载均衡和调度,相当于mvc中的controller的角色,在访问上起负载均衡的作用。跟踪器和存储节点都可以由一台或多台服务器构成,跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务,其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。

Storage server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage server没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。
如下图:

Docker部署FastDFS分布式文件存储_docker

tracker节点:存储数据的元数据节点,此节点存放的是所有数据的元数据,如数据路径,保存时间等信息。其信息是storage节点定时上传到tracker节点的。

storage节点:用于存放数据,storage节点的特点是两个或多个节点为一组构成一个集群,类似于镜像集群,数据只存放于两台上任意一台,而另一台则自动从另一台同步数据,保证数据为双份或多份。

3.FastDFS的特点:

1、分组存储、灵活简洁 
2、对等结构、不存在单点
3、文件ID有FastDFS生成,作为文件访问凭证。FastDFS不需要传统的name server
4、和流行的web server无缝连接,FastDFS已提供apache和nginx扩展模块
5、大、中、小文件均可以很好支持,支持海量小文件存储
6、支持多块磁盘,支持但盘数据恢复
7、支持相同文件内容只保存一份,节省存储空间
8、存储服务器上可以保存文件附加属性
9、下载文件支持多线程方式、支持断点续传

4.Fastdfs访问步骤

Docker部署FastDFS分布式文件存储_服务器_02
上传文件步骤

1.客户端上传文件请求,请求到到tracker节点;
2.tracker节点基于内部算法选择合适的storage节点发送给客户端;
3.客户端访问指定的storage节点,然后保存到指定storage上;

访问文件步骤

4.客户端发起请求到tracker节点;
5.tracker节点基于请求文件路径可以得出文件存放在哪个storage节点上,因为请求文件名是包含路由信息的;
6.tracker节点返回storage节点信息给client,client访问storage节点拿到数据;

5.Docker部署FastDFS服务器

1.搜索镜像

docker search fastdfs

2.拉取镜像

docker pull morunchang/fastdfs

3.查看镜像

docker images

4.运行tracker 跟踪器

docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh

5.运行storage 存储器

docker run -d --name storage --net=host -e TRACKER_IP=122.51.50.249:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh

6.修改nginx的配置,不拦截上传内容

– 进入容器内部

docker exec -it storage  /bin/bash
cd data
ls

– 修改nginx配置文件

vi /data/nginx/conf/nginx.conf

– 添加修改内容

location /group1/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http-cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group1;
expires 30d;
}

Docker部署FastDFS分布式文件存储_文件上传_03
– 退出

exit

7. 重启storage服务

docker restart storage

6.Java客户端使用

6.1.导依赖

Docker部署FastDFS分布式文件存储_服务器_04

mvn install:install-file -Dfile=D:\8888\fastdfs_client-1.25.jar -DgroupId=fastdfs_client -DartifactId=fastdfs_client -Dversion=1.25 -Dpackaging=jar

注意:maven中央仓库并没有这个依赖,需要自行寻找资源并安装到本地maven仓库,才能正常使用下方的依赖

<!--FastDFS-->
<dependency>
<groupId>fastdfs_client</groupId>
<artifactId>fastdfs_client</artifactId>
<version>1.25</version>
</dependency>

<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

6.2.测试方法

package com.bruce.test;

import org.csource.common.MyException;
import org.csource.fastdfs.*;
import org.junit.Test;

import java.io.IOException;

/**
* @BelongsProject: FastFDS_Java
* @BelongsPackage: com.bruce.test
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2018-01-30 22:55
* @Description: 测试文件上传
*/
public class FileUploadTest {
/*
* 步骤:
* 1、使用ClientGlobal的静态方法加载Tracker服务器配置信息(注意:必须为全路径)
* 2、创建TrackerClient对象
* 3、使用TrackerClient获取TrackerServer对象
* 4、创建StorageServer对象,引用为null即可
* 5、使用TrackerServer和StorageServer构造StorageClient对象
* 6、使用StorageClient进行文件上传
* 7、返回的字符串数组为上传文件在服务器中所在位置以及文件名
*/
@Test
public void fileUpload() throws IOException, MyException {
//加载连接信息(即FastDFS中tracker服务器IP)
ClientGlobal.init("D:\\test\\fdfs_client.conf");
//创建TrackerClient对象\
TrackerClient trackerClient = new TrackerClient();
//获取TrackerServer对象
TrackerServer trackerServer = trackerClient.getConnection();
//创建StorageServer对象,引用为空
StorageServer storageServer = null;
//使用TrackerServer和StorageServer构造StorageClient对象
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
//使用storageClient上传文件到服务器
String[] strings = storageClient.upload_file("D:\\test\\test.png", "png", null);
//上传成功会返回一个字符数组,分别为:文件所在组和文件在组中的位置及名称
for(String s:strings){
System.out.println(s);
}
}
}

运行结果:

group1
M00/00/00/rBEAD16CC9yAFqumAANWuI72LJc131.png

访问上传地址:
​​​http://122.51.50.249:8080/group1/M00/00/00/rBEAD16CC9yAFqumAANWuI72LJc131.png​​​Docker部署FastDFS分布式文件存储_docker_05

7.封装封装文件上传工具类

7.1.工具类

package com.bruce.utils;

import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;

/**
* @BelongsProject: FastFDS_Java
* @BelongsPackage: com.bruce.utils
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2029-01-30 23:15
* @Description: TODO
*/

public class FastDFSClient {

private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;

public FastDFSClient(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}

/**
* 上传文件方法
* <p>Title: uploadFile</p>
* <p>Description: </p>
*
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}

public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}

public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}

/**
* 上传文件方法
* <p>Title: uploadFile</p>
* <p>Description: </p>
*
* @param fileContent 文件的内容,字节数组
* @param extName 文件扩展名
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {

String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}

public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}

public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}

7.2.测试工具类

package com.bruce.test;

import com.bruce.utils.FastDFSClient;
import org.junit.Test;

/**
* @BelongsProject: FastFDS_Java
* @BelongsPackage: com.bruce.test
* @Author: bruceliu
* @QQ:1241488705
* @CreateTime: 2020-03-30 23:16
* @Description: FastDFS工具类使用
*/
public class TestUtils {

@Test
public void fileUploadUtil() throws Exception {
//使用Tracker服务器信息配置文件位置构造工具类对象
FastDFSClient util = new FastDFSClient("D:\\test\\fdfs_client.conf");
//上传文件到文件服务器
String s = util.uploadFile("D:\\test\\1234.jpg");
//打印文件在服务器所在位置
System.out.print(s);
}
}