FastDFS概述_简介
FastDFS是一个开源的轻量级分布式文件系统。它解决了大数据量存储和负载均衡等问题。特别适合以中小文件(
建议范围:4KB <file_size <500MB)
为载体的在线服务,如相册网站、视频网站等等。
FastDFS特性:
- 文件不分块存储,上传的文件和OS文件系统中的文件一一对应
- 支持相同内容的文件只保存一份,节约磁盘空间
- 下载文件支持HTTP协议,可以使用内置Web Server,也可以和其他Web Server配合使用
- 支持在线扩容
- 支持主从文件
FastDFS概述_核心概念
![](https://img-blog.csdnimg.cn/direct/23b29a45f7934220ac3b20fa682f8687.png)
tracker
跟踪服务器,主要做调度工作,起负载均衡的作用。在内存中记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。
storage
存储服务器(又称:存储节点或数据服务器),文件和文件属性(meta data)都保存到存储服务器上。
Storage server
直接利用OS的文件系统调用管理文件。
client
客户端,作为业务请求的发起方,通过专有接口,使用TCP/IP
协议与跟踪器服务器或存储节点进行数据交互。FastDFS
向使用者提供基本文件访问接口,比如upload
、
download
、
append
、
delete等,以客户端库的方式提供给用户使用。
group
组, 也可称为卷。 同组内服务器上的文件是完全相同的 ,同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server
上进行 。
![](https://img-blog.csdnimg.cn/direct/87fabb7512d34c2581567efc77e26934.png)
流程:
Tracker相当于
FastDFS
的大脑,不论是上传还是下载都是通过tracker来分配资源;客户端一般可以使用
Ngnix
等静态服务器来调用或者做一部分的缓存;存储服务器内部分为卷(或者叫做组),卷于卷之间是平行的关系,可以根据资源的使用情况 随时增加,卷内服务器文件相互同步备份,以达到容灾的目的。
FastDFS概述_上传机制
![](https://img-blog.csdnimg.cn/direct/3d38aa8491534f7d957118706223fb5e.png)
流程:
首先客户端请求Tracker
服务获取到存储服务器的
ip
地址和端口,然后客户端根据返回的IP
地址和端口号请求上传文件,存储服务器接收到请求后生产文件,并且将文件内容写入磁盘并返回给客户端file_id、路径信息、文件名等信息,客户端保存相关信息上传完毕。
内部机制如下
1、选择Tracker server
当集群中不止一个Tracker server
时,由于
Tracker
之间是完全对等的关系,客户端在upload
文件时可以任意选择一个
trakcer
。
2、选择Storage server
当选定Group
后,
Tracker
会在
Group
内选择一个
Storage Server
给客户端
3、选择Storage path
当分配好Storage Server
后,客户端将向
Storage
发送写文件请求,Storage将会为文件分配一个数据存储目录。
注意:
剩余存储空间最多的优先。
4、生成Fileid
选定存储目录之后,Storage
会为文件生一个
Fileid
,由
Storage Server Ip、文件创建时间、文件大小、文件
crc32
和一个随机数拼接而成,然后将这个二进制串进行base64
编码,转换为可打印的字符串。
5、生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid
、文件后缀名(由客户端指定,主要用于区分文件类型) 拼接而成。
FastDFS概述_下载机制
流程:
客户端带上文件名信息请求Tracker
服务获取到存储服务器的
ip
地址和端口,然后客户端根据返回的IP
地址和端口号请求下载文件,存储服务器接收到请求后返回文件给客户端。
![](https://img-blog.csdnimg.cn/direct/2bb9206184f4445298af47376650293d.png)
内部机制如下
- 1 client询问tracker下载文件的storage,参数为文件标识(组名和文件名)
- 2 tracker返回一台可用的storage
- 3 client直接和storage通讯完成文件下载
FastDFS环境搭建_Linux
下载安装gcc
安装方式为
yum
安装(需网络):
1 |
yum install gcc-c++ perl-devel pcre-devel openssl-devel zlib-devel wget
|
下载安装FastDFS
2 |
wget https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz
|
下载安装FastDFS依赖
3 |
wgethttps://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz
|
解压缩依赖tar包
4 |
tar -zxvf V1.0.43.tar.gz -C /usr/local
tar -zxvf V5.11.tar.gz -C /usr/local
|
编译并安装libfastcommon
5 |
cd /usr/local/libfastcommon-1.0.43/
./make.sh && ./make.sh install
|
编译并安装FastDFS
6 |
cd /usr/local/fastdfs-6.06
./make.sh && ./make.sh install
|
进入etc目录下复制配置文件
7 |
cd /etc/fdfs/
cp client.conf.sample client.conf
cp storage.conf.sample storage.conf
cp tracker.conf.sample tracker.conf
|
创建tracker服务
创建tracker目录
8 |
mkdir -p /data/fastdfs/tracker
|
修改配置文件
9 |
vim /etc/fdfs/tracker.conf
disabled=false #
启用配置文件
port=22122 #
设置
tracker
的端口号
base_path=/data/fastdfs/tracker #
设置
tracker
的数据文件和日志目录(需预先创建)
http.server_port=8888 #
设置
http
端
口号
http.server_port=8888 #
指的是在
tracker
服务器上启动
http
服务进程,如
:apache
或者
nginx
启动时所监听的端口
|
启动tracker服务
10 | /etc/init.d/fdfs_trackerd start |
检查tracker服务
11 |
netstat -lntup |grep fdfs
|
创建storage服务
创建storage目录
12 |
mkdir -p /data/fastdfs/base
mkdir -p /data/fastdfs/storage
|
修改配置文件
13 |
vim /etc/fdfs/storage.conf
disabled=false #
启用配
置文件
group_name=group1 #
组名,
根据实际情况修改
port=23000 #
设置
storage
的端口号
base_path=/data/fastdfs/base #
设置
storage
的日志目录(需预先创建)
store_path_count=1 #
存储路
径个数,需要和
store_path
个数匹配
store_path0=/data/fastdfs/storage #
存储
路径
tracker_server=172.31.16.121:22122
#tracker
服务器的
IP
地址和端口号
http.server_port=8888 #
设置
storage
上启动的
http
服务的端口号,如安装的
nginx
的端
口号
|
启动storage服务
14 |
/etc/init.d/fdfs_storaged start
|
查看storage服务
15 |
netstat -lntup |grep fdfs
|
修改Client配置文件
16 |
vim /etc/fdfs/client.conf
connect_timeout=30
network_timeout=60
base_path=/data/fastdfs/client
#
日志
路径
tracker_server=192.168.66.100:22122
#
追
踪服务器的
IP
,有多个服务器可以另一行
|
创建日志目录
17 |
mkdir -p /data/fastdfs/client
|
查看启动的服务
18 |
ps -ef | grep fdfs
|
FastDFS指令
![](https://img-blog.csdnimg.cn/direct/f97058febcd44018bd5cf099d92ae07e.png)
上传指令
指令参数 ![](https://img-blog.csdnimg.cn/direct/b551fba0fa01468e905030618454076e.png)
参数含义:
- 1 <config_file> :配置文件路径
- 2 <local_filename> :本地文件路径
- 3 [storage_ip:port] :(可选参数)
- 4 [store_path_index] :(可选参数)
指令使用
19 |
[root@tracker fdfs]# fdfs_upload_file
/etc/fdfs/client.conf
上传的文件路径
|
注意:
上传文件后会返回文件在FastDFS
中的唯一文件标识,即卷名+文件名
下载指令
指令参数
20 |
fdfs_download_file <config_file> <file_id>
[local_filename] [<download_offset>
<download_bytes>]
|
参数含义:
- 1 <config_file> :配置文件路径
- 2 <file_id> :文件在FastDFS中的唯一文件标识,即卷名+文件名
- 3 [local_filename] :文件下载地址
- 4 <download_offset> :(可选参数)文件下载开始时间
- 5 <download_bytes> :(可选参数)文件下载的字节数
指令使用
21 |
[root@tracker fdfs]# fdfs_download_file
/etc/fdfs/client.conf
group1/M00/00/00/wKhygVwnUUOAcgYHCCZp2Ahsb3g9
64.rpm /root/java/xxx.rpm
|
查看文件信息指令
指令参数
22 |
fdfs_file_info <config_file> <file_id>
|
参数含义:
- 1 <config_file> :配置文件路径
- 2 <file_id> :文件在FastDFS中的唯一文件标识,即卷名+文件名
指令使用
23 |
[root@tracker fdfs]# fdfs_file_info
/etc/fdfs/client.conf
group1/M00/00/00/wKhygVwnUUOAcgYHCCZp2Ahsb3g9
64.rpm
|
删除指令
指令参数
24 |
fdfs_delete_file <config_file> <file_id>
|
参数含义:
- 1 <config_file> :配置文件路径
- 2 <file_id> :文件在FastDFS中的唯一文件标识,即卷名+文件名
指令使用
25 |
[root@tracker fdfs]# fdfs_delete_file
/etc/fdfs/client.conf
group1/M00/00/00/wKhygVwnUUOAcgYHCCZp2Ahsb3g9
64.rpm
|
注意
:
删除指令使用后,文件在该卷中的所有备份都会被删除,因为 卷内的存储节点会相互同步,故慎用。
SpringBoot操作FastDFS
![](https://img-blog.csdnimg.cn/direct/c8eccaea5ac442179925502a27e5fdaf.png)
主要特性
- 1 对关键部分代码加入了单元测试,便于理解与服务端的接口交易,提高接口质量
- 2 将以前对byte硬解析风格重构为使用对象+注解的形式,尽量增强了代码的可读性
- 3 支持对服务端的连接池管理
- 4 支持上传图片时候检查图片格式,并且自动生成缩略图
- 5 在SpringBoot当中自动导入依赖
实战开发
导入FastDFS依赖jar
1 |
<dependency>
<groupId>
com.github.tobato
</groupId>
<artifactId>
fastdfs-client
</artifactId>
<version>
1.26.5
</version>
</dependency>
|
配置SpringBoot的入口类
2 |
package
com
.
demo
;
import
com
.
github
.
tobato
.
fastdfs
.
FdfsClientConfig
;
import
org
.
springframework
.
boot
.
SpringApplication
;
import
org
.
springframework
.
boot
.
autoconfigure
.
Sprin
gBootApplication
;
import
org
.
springframework
.
context
.
annotation
.
Enabl
eMBeanExport
;
import
org
.
springframework
.
context
.
annotation
.
Impor
t
;
import
org
.
springframework
.
jmx
.
support
.
Registration
Policy
;
//==========================================
=========================
//
获取带有连接池的
FastDFS Java
客户端
@Import
(
FdfsClientConfig
.
class
)
//
解决
jmx
重复注册
bean
的问题
@EnableMBeanExport
(
registration
=
RegistrationPolicy
.
IGNORE_EXISTING
)
//==========================================
=========================
@SpringBootApplication
public class
FastdfsSpringbootDriverApplication
{
public static
void
main
(
String
[]
args
) {
SpringApplication
.
run
(
FastdfsSpringbootDriv
erApplication
.
class
,
args
);
}
}
|
配置springboot的application.yml配置文件
3 |
#
分布式文件系统
FDFS
配置
fdfs:
so-timeout: 1501
connect-timeout: 601
thumb-image: #
缩略图生成参数
width: 150
height: 150
tracker-list: #TrackerList
参数
,
支持多个
- 192.168.66.100:22122
- 192.168.66.101:22122
|
上传文件操作
4 |
/**
*
测试
springboot
环境下的
javaAPI
对分布式文件
系统的上传文件的操作
* @throws FileNotFoundException
*/
@Test
public void testUpload() throws
FileNotFoundException {
//
获取本地文件
File file = new File("G:\\
图片
\\mei.jpg");
//
创建传输文件的输入流
FileInputStream fileInputStream =
new FileInputStream(file);
//
文件上传:参数一:传输文件内容的输入流;
参数二:文件的
size
;参数三:文件扩展名;参数四:描述
文件的元数据;返回值:上传文件在存储节点的唯一标识
(卷名
+
文件名)
StorePath storePath =
fastFileStorageClient.uploadFile(fileInputSt
ream, file.length(), "jpg", null);
//
将卷名与文件名一起打印
System.out.println(storePath.getFullPath());
//
将卷名与文件名分别打印
System.out.println(storePath.getGroup()+" |
"+storePath.getPath());
}
|
文件下载的操作
4 |
/**
*
测试
springboot
环境下的
javaAPI
对分布式文件
系统的下载文件的操作
* @throws IOException
*/
@Test
public void testDownload() throws
IOException {
//
下载文件:参数一:文件处于存储节点的卷
名;参数二:文件在存储节点的文件名;参数三:下载的回
调函数;返回值:文件内容的字节数组
byte[] bytes =
fastFileStorageClient.downloadFile("group1",
"M00/00/00/wKhCZWICJcqAftV0AAChCwXlPdE133.jp
g", new DownloadByteArray());
//
创建文件输出流,指定输出位置及文件名
FileOutputStream fileOutputStream =
new FileOutputStream("G:\\mei.jpg");
//
使用文件输出流将文件内容字节数组写出
fileOutputStream.write(bytes);
//
刷新输出流
fileOutputStream.flush();
//
关闭输出流
fileOutputStream.close();
}
|
文件上传_SpringBoot基于FastDFS实现
![](https://img-blog.csdnimg.cn/direct/89951a615a7d4092b0716646b416dc1a.png)
引入Thymeleaf视图解析器
1 |
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter
thymeleaf
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
|
下载wangEditor富文本编辑器
![](https://img-blog.csdnimg.cn/direct/c0995ca0f2134d5291698420eaf4cf2f.png)
编写index页面
2 |
<!DOCTYPE html>
<html
lang
=
"en"
xmlns:th
=
"http://www.thymeleaf.org"
>
<head>
<meta
charset
=
"UTF-8"
>
<title>
wangEditor demo
</title>
</head>
<body>
<div
id
=
"div1"
>
<p>
欢迎使用
<b>
wangEditor
</b>
富文本编辑器
</p>
</div>
<script
type
=
"text/javascript"
th:src
=
"@{wangEditor.min.js}"
src
=
"../static/wangEditor.min.js"
></script>
<script
type
=
"text/javascript"
>
const
E
=
window
.
wangEditor
const
editor
=
new
E
(
'#div1'
)
//
设置文件上传的参数名称
editor
.
config
.
uploadFileName
=
'files'
//
配置
server
接口地址
editor
.
config
.
uploadImgServer
=
'/upload/uploadMoreImage.do'
// 2M
editor
.
config
.
uploadImgMaxSize
=
2
*
1024
*
1024
editor
.
config
.
uploadImgAccept
=
[
'jpg'
,
'jpeg'
,
'png'
,
'gif'
,
'bmp'
,
'webp'
]
//
一次最多上传
5
个图片
editor
.
config
.
uploadImgMaxLength
=
5
editor
.
create
()
</script>
</body>
</html>
|
编写Controller接口
3 |
@RestController
@RequestMapping
(
"/upload"
)
public class
UoloadToFastDFSController
{
//fastdfs
存储节点的客户端对象
@Autowired
private
FastFileStorageClient
fastFileStorageClient
;
@GetMapping
(
"/upload"
)
public
void
uploadMoreImage
(
MultipartFile
[]
files
){
//
判断是否上传图片
if
(
files
!=
null
&&
files
.
length
!=
0
){
//
遍历上传图片
for
(
MultipartFile multipartFile
:
files
) {
//
获取上传文件名
String
filename
=
multipartFile
.
getOriginalFilename
();
//
获取最后一个
“.”
的下标,并获取从
这个下标的下一个下标开始后的字符作为文件后缀
String
fileSuffix
=
filename
.
substring
(
filename
.
lastIndexOf
(
"."
)
+
1
);
StorePath storePath
=
null
;
try
{
//
上传文件
storePath
=
fastFileStorageClient
.
uploadFile
(
multipartFi
le
.
getInputStream
(),
multipartFile
.
getSize
(),
fileSuffix
,
null
);
}
catch
(
IOException e
) {
e
.
printStackTrace
();
}
//
打印返回的文件在存储节点的唯一标
识
System
.
out
.
println
(
storePath
.
getFullPath
());
}
}
}
}
|
FastDFS集成Nginx
![](https://img-blog.csdnimg.cn/direct/1881edffa7c143b1acc5201591ab7e85.png)
Nginx服务器是一个高性能的
web
服务器与反向代理服务器。
FastDFS集成Nginx的2个原因
分布式文件系统提供Http服务支持
通过Nginx
的
web
服务代理访问分布式文件系统的存储节点,从而实 现通过http请求访问存储节点资源。
![](https://img-blog.csdnimg.cn/direct/4d8f6c3e36274173b177e499d729d665.png)
注意:
src 属性值图像文件的
URL
。也就是引用该图像的文件的的绝对路径或相对路径。
解决复制延迟问题
由于FastDFS
的同卷的存储节点之间需要同步,当文件尚未同步完时,访问请求到达改节点,获取的数据将是未同步完的不完整数据,即为复制延迟问题。通过Nginx
检测请求的存储节点的数据,若该存储节点的数据尚未同步完成,则将请求转发至数据的原存储节点,从而解决复制延迟问题。
FastDFS集成Nginx_环境搭建
![](https://img-blog.csdnimg.cn/direct/194c0e00491b4fb2b1b9ec7968893bdf.png)
下载Fastdfs的Nginx模块包
1 |
cd /usr/local
wget https://github.com/happyfish100/fastdfs
nginx-module/archive/V1.22.tar.gz
tar -zxvf V1.22.tar.gz
|
安装Nginx依赖文件
2 |
yum install -y gcc gcc-c++ zlib zlib-devel
openssl openssl-devel pcre pcre-devel gd
devel epel-release
|
下载Nginx软件包
3 |
wget https://nginx.org/download/nginx-
1.19.2.tar.gz
cd nginx-1.19.2/
|
配置Nginx服务器
4 |
#
建立
Makefile
文件,检查
Linux
系统环境以及相关的关键
属性。
./configure --add-module=/usr/local/fastdfs
nginx-module-1.22/src/
#
编译项目,主要将
gcc
源代码编译成可执行的目标文件
make
#
根据上一步骤编译完成的数据安装到预定的目录中。
make install
|
注意:
- –add-module:为nginx添加一个fastdfs-nginx-module模块,值为该模块在当前系统的路径
- –prefix:指定nginx安装位置
将Fastdfs软件包里面的http.conf和mime.types拷贝到/etc/fdfs目录下
1 |
cp /usr/local/src/fastdfs-
6.06/conf/mime.types /etc/fdfs/
cp /usr/local/src/fastdfs-6.06/conf/http.conf
/etc/fdfs/
|
配置Nginx的fastdfs模块,并编辑文件
2 |
#
拷贝文件
[root@localhost opt]cp /usr/local/fastdfs
nginx-module-1.22/src/mod_fastdfs.conf
/etc/fdfs/
[root@localhost fdfs] vim mod_fastdfs.conf
#
保存日志目录
base_path=/data/fastdfs/storage
#tracker
服务器的
IP
地址以及端口号
tracker_server=192.168.66.100:22122
#
文件
url
中是否有
group
名
url_have_group_name = true
#
存储路径
store_path0=/data/fastdfs/storage
group_count = 1 #
设置组的
个数
#
然后在末尾添加分组信息,目前只有一个分组,就只写一个
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs/storage
|
配置Nginx
3 |
server
{
listen
80;
server_name
localhost;
location
~
/group[
1-3
]/
M00
{
alias
/data/fastdfs/storage/data;
ngx_fastdfs_module;
}
#
根目录下返回
403
location
= / {
return
403;
}
# log file
access_log
logs/img_access.
log access
;
}
|
启动Ningx服务
4 |
#
进入
sbin
目录
[root@tracker nginx]# cd sbin/
#
启动服务
-c
:指定配置文件
[root@tracker sbin]# ./nginx -c
/usr/local/nginx/conf/nginx.conf
|
查看服务启动情况
5 |
[root@tracker sbin]# ps -ef | grep nginx
|
启动追踪服务与存储节点服务
6 |
[root@tracker sbin]# fdfs_trackerd
/etc/fdfs/tracker.conf start
[root@tracker sbin]# fdfs_storaged
/etc/fdfs/storage.conf start
|
通过浏览器远程访问
7 |
http://192.168.66.100/group1/M00/00/00/wKhyj1
wrIfqAD3NFAAn1fNRE8_M976.png
|