1简介/架构
1.1简单介绍
分布式文件系统,看名字就知道,它可以存储在不同的机器上。肯定也要有路由功能。
特点
备份容错,负载均衡,动态扩容
场景
0-500MB之间大小的文件存储(图片,短视频,文档。。。)
1.2 架构
client客户端
Tracker Server 跟踪节点
- 负责接收客户端请求,选择合适的Storage Server来保存文件,还要和Storage Server保持心跳机制来做健康检查
- 如何选择合适的Storage Server节点去存储文件?:磁盘状况,负载状况等。
- Tracker Server 集群节点都是对等的,可以增加节点
Storage Server 存储节点
- 实际的存储单元,分成若干个组(group) ,每个组的数据都是一样的。 group才是真正存储数据的地方。
- Tracker Server实际管理的是 Storage Server的group.
2 安装(单机)
1安装基础库
yum -y install tcl telnet vim lrzsz zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-devel libevent libevent-devel perl unzip net-tools wget
2上传文件
3安装libfastcommon(fastdfs运行的一些基础库)
解压
tar -zxvf libfastcommonV1.0.7.tar.gz
4 进入解压目录
cd libfastcommon-1.0.7/
5编译
./make.sh && ./make.sh install
注意:libfastcommon 安装好后会自动的将库文件拷贝至 /usr/lib64下,由于fastDFS程序引用 /usr/lib 目录 ,所以需要将 /usr/lib64 下的库文件拷贝到 /usr/lib下 (有的版本已经自己复制过去了)
find / -name libfastcommon.so
6 将 libfastcommon.so 从/usr/lib64 复制到 /usr/lib
cp /usr/lib64/libfastcommon.so /usr/lib
安装FastDFS_v5.05(tracker+storage)
注意此处我们将这俩安装在同一个机器上,真实的服务器应该分开部署,
7 解压FastDFS_v5.05.tar.gz
tar -zxvf FastDFS_v5.05.tar.gz
8 进入解压目录
cd FastDFS
9编译安装
./make.sh && ./make.sh install
10 进入FastDFS的conf目录下
cd conf/
11 将 conf目录下所有文件 复制到 /etc/fdfs/
cp * /etc/fdfs/
部署 tracker
部署集群方式还是单机方式,上面的编译都需再来一遍的。 底下的 tracker部署 或者 Storage部署都是可以分机部署,只需要存储节点的配置文件的 trackerip配置正确即可
12 安装 跟踪节点服务(tracker)
vim /etc/fdfs/tracker.conf
tracker.conf配置文件需要修改的地方
# empty for bind all addresses of this host
bind_addr=
# tracker 数据和日志的 保存位置
base_path=/usr/local/FastDFS/tracker
#底下配置默认即可
# 上传文件的方式 0是轮序 1指定一个专门的组 2选择可用空间最大的组 默认即可
store_lookup=2
http.server_port=8080
port=22122
启动 tracker (日志路径看 base_path)
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
重启tracker (日志路径看 base_path) 停止就在后面加 stop
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
配置开机自启动
vim /etc/rc.local
感觉应该要写脚本,直接添加启动命令不好使 如下图
13存储节点安装(Storage)port:23000
1如果是在不同的服务器安装,则前面的两步需要重新执行。
配置Storage服务
vim /etc/fdfs/storage.conf
需要改变的配置(storage.conf)
# 配置数据和日志目录 存放目录
base_path=/usr/local/FastDFS/storage/base
#配置上传文件存放目录
store_path0=/usr/local/FastDFS/storage/store
# 要配置tracker服务的公网ip
tracker_server=192.168.209.121:22122
#默认配置即可
port=23000
#集群模式下 (2台storage 主从备份的话 group_name要相同) 四台机器(2主2从 那就得两个组名) 因为同一个组下数据是一样的 单机不用管
group_name=group1
启动storage服务
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf
14 配置客户端
这是我解压的目录FastDFS_v5.05.tar.gz
/usr/local/data/fastdfs/FastDFS
去解压目录中的client中将 libfdfsclient.so 拷贝到 /usr/lib 这一步非常关键(ngxin)
cd client/
cp libfdfsclient.so /usr/bin/
编辑客户端配置文件
vim /etc/fdfs/client.conf
配置文件(client.conf)
# 数据 日志存放目录
base_path=/usr/local/FastDFS/client
# 跟踪服务器地址端口 (这个不是本机而是对外访问的ip)
tracker_server=192.168.189.132:22122
测试 创建一个hi.html 并上传 返回地址 (但是访问不了的,需要nginx搭配)
touch /root/hi.html
/usr/bin/fdfs_test /etc/fdfs/client.conf upload /root/hi.html
验证存放数据的目录 (store_path0配置的路径)
cd /usr/local/FastDFS/storage/store/data/00/00
部署nginx
安装环境
yum -y install gcc pcre-devel zlib-devel openssl openssl-devel
## 解压
tar -zxvf nginx-1.9.9.tar.gz
##进入nginx目录
cd nginx-1.9.9
解压nginx与fast模块
tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
模块复制配置文件 到etc下
cp fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
修改配置文件
vim /etc/fdfs/mod_fastdfs.conf
mod_fastdfs.conf配置文件的修改 (集群模式看这个连接)
010_mod_fastdfs.conf配置详情_自由与束缚JavaJavaScript的博客-CSDN博客_mod_fastdfs.conf
tracker_server=192.168.189.132:22122
url_have_group_name = true
# 要和存储节点路径保持一致,要不nginx找不到文件
store_path0=/usr/local/FastDFS/storage/store
安装nginx新模块,别把老模块误删除
#后面路径fastdfs-nginx-module解压得路径+/src
#必须在nginx目录下执行命令
./configure --add-module=/usr/local/data/fastdfs/fastdfs-nginx-module/src
编译 (自动安装在 /usr/local/nginx)
make && make install
报错的话 (fastdfs+nginx make时报错fatal error:fdfs_define.h: 没有那个文件或目录 - 不是伟人 - 博客园)
编辑nginx配置文件
vim /usr/local/nginx/conf/nginx.conf
最好配置缓存,加速访问。
#方式一写死了
location /group1/M00/ {
root /usr/local/FastDFS/storage;
ngx_fastdfs_module;
}
#方式二正则匹配,很多组都行
location ~/group([0-9])/M00/ {
# storage的文件存储路径
root /usr/local/FastDFS/storage;
ngx_fastdfs_module;
}
保存,退出,启动nginx
cd /usr/local/nginx/sbin/
./nginx
java代码
<!-- 连接fastdfs文件系统
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency> -->
<!-- springboot整合的 使用更加便捷-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
</dependency>
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
/**
* @创建人
* @创建时间 2023/1/8
* @描述 Fastdfs客户端工具类
*/
@Component
public class FdfsClientService {
@Autowired
private FastFileStorageClient fastFileStorageClient;
/**
*
* @param file
* @return group1/M00/00/00/wKiHBmO6y4qAFAGVAAEGLuSI-lU542.jpg
* @throws IOException
*/
public String uploadFile(MultipartFile file) throws IOException {
if (file != null) {
byte[] bytes = file.getBytes();
long fileSize = file.getSize();
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
return this.uploadFile(bytes, fileSize, extension);
}
return null;
}
/**
* 文件上传
*
* @param bytes 文件字节
* @param fileSize 文件大小
* @param extension 文件扩展名
* @return 返回文件路径(卷名和文件名)
*/
public String uploadFile(byte[] bytes, long fileSize, String extension) {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
// 元数据
Set<MetaData> metaDataSet = new HashSet<MetaData>();
metaDataSet.add(new MetaData("dateTime", LocalDateTime.now().toString()));
metaDataSet.add(new MetaData("Author","Layne"));
StorePath storePath = fastFileStorageClient.uploadFile(bais, fileSize, extension, metaDataSet);
return storePath.getFullPath();
}
/**
* 下载文件
*
* @param filePath 文件路径 group1/M00/00/00/wKiHBmO6y4qAFAGVAAEGLuSI-lU542.jpg
* @return 文件字节
* @throws IOException
*/
public byte[] downloadFile(String filePath) throws IOException {
byte[] bytes = null;
if (StringUtils.isNotBlank(filePath)) {
String group = filePath.substring(0, filePath.indexOf("/"));
String path = filePath.substring(filePath.indexOf("/") + 1);
DownloadByteArray byteArray = new DownloadByteArray();
bytes = fastFileStorageClient.downloadFile(group, path, byteArray);
}
return bytes;
}
/**
* 删除文件
*
* @param filePath 文件路径 group1/M00/00/00/wKiHBmO6y4qAFAGVAAEGLuSI-lU542.jpg
*/
public void deleteFile(String filePath) {
if (StringUtils.isNotBlank(filePath)) {
fastFileStorageClient.deleteFile(filePath);
}
}
}