FastDFS体验
一、FastDFS简介:
分布式文件服务器;
FastDFS的Docker封装包含三个部分:tracker, storage, Nginx;
FastDFS默认占用三个端口:
8888:默认是nginx代理的端口,访问上传文件的URL地址就是用的这个端口
23000:storage服务端口
22122:tracker服务端口
二、FastDFS部署:
1、拉取镜像:
docker pull delron/fastdfs:latest
2、创建文件存储文件夹:
mkdir -p /data/tracker mkdir -p /data/storage
3、创建tracker容器:
docker run -id --name tracker --restart=always --net host -v /etc/localtime:/etc/localtime -v /data/tracker:/var/fdfs delron/fastdfs tracker
4、创建storage容器:
docker run -id --name storage --restart=always --net host -v /etc/localtime:/etc/localtime -v /data/storage:/var/fdfs -e TRACKER_SERVER="IP:22122" -e GROUP_NAME=group1 delron/fastdfs storage
5、进入storage容器内部:
docker exec -it 容器id bash
6、FastDFS的Nginx模块代理默认使用的是8888端口,这个端口跟其他端口冲突的可能性很大,建议把这个端口修改下,进入storage容器内部通过下面的命令进行修改:
1、修改storage配置:
vi /etc/fdfs/storage.conf http.server_port=8888 //修改8888为8850
2、修改nginx配置:
vi /usr/local/nginx/conf/nginx.conf listen 8888; //修改8888为8850
3、退出容器:
exit
4、重启容器:
docker restart 容器id docker restart storage bash
7、测试:
1、进入容器内部;
2、进入fdfs文件夹并放一个测试文件01.jpg:
cd /var/fdfs
3、执行上传命令:
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf 01.jpg
执行完命令后会返回一个文件的URL地址,加上前缀(http://IP:8850)就可以直接访问
三、部署常见问题:
1.创建storage容器时不能修改分组名:
这个地方有个坑点,创建Storage容器时可以参数GROUP_NAME指定分组名称,默认是group1,笔者试着将这么名称改为”group_XXX”,结果启动时从日志中可以看到说分组名称“group_XXX”是一个不合法的分组名称,看来分组名称是不能带下划线,于是笔者又将下划线去掉,改为了“groupXXX”,启动没有任何问题,上传文件也没问题,也能正常返回上传的文件地址,但是这个地址访问始终就是404,知道后来在nginx的配置文件中发现下面这个信息才恍然大悟,分组名称必须是group后面加数字,如果要改成其他形式的分组名称,nginx配置的这个地方也要改。笔者把分组名称改为默认的“group1”后就一切正常了。
2.防火墙的设置:
如果不关闭防火墙,发现其他机器对FastDFS都不能访问,关闭防火墙就可以正常访问,防火墙相关命令:
开启防火墙:
systemctl start firewalld.service
关闭防火墙:
systemctl stop firewalld.service
查看防火墙状态:
systemctl status firewalld.service
但是关闭防火墙又会造成安全隐患,因此防火墙可以开启,但是只是针对FastDFS的端口开放,命令如下:
sudo firewall-cmd --zone=public --add-port=23000/tcp --permanent
sudo firewall-cmd --zone=public --add-port=22122/tcp --permanent
sudo firewall-cmd --zone=public --add-port=8850/tcp --permanent
3.笔者在调试时,前端上传用的Vue的el-upload组件,设置了显示上传进度条,但是发现无论如何都不能生效,百思不得其解,于是把FastDFS换成SpringBoot自带的MultipartFile,进度条居然能显示了,很是奇怪,更奇怪的是系统部署到生产环境后,由于用的是域名访问,用FastDFS上传的居然又能显示进度条了,真奇怪。
4.FastDFS比较适合于一些小文件的传输,比如象用户图像和一些图片之类的,但是对于比较大的文件就不太适合了,笔者在调试时发现上传大文件还没有SpringBoot自带的MultipartFile上传的快(网上有说大文件可以分片上传,不过我没研究过)。
四、SpringBoot接入:
1、添加依赖:
<!--分布式文件存储 fastDFS-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
<!--上传下载 间接包-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
2、在springboot启动类中加上以下两个注解:
//加载fastDFS
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
@Import(FdfsClientConfig.class)
3、配置application.properties文件:
# 配置fastdfs的连接地址等信息
fdfs.connect-timeout=1000
fdfs.so-timeout=1500
# 注意这个trackerList:如果是集群tracker的话以逗号分隔开就行
fdfs.tracker-list=localhost:22122
fdfs.pool.max-total=200
# 最大上传单个文件大小:默认1M
spring.servlet.multipart.max-file-size=500MB
# 最大置总上传的数据大小 :默认10M
spring.servlet.multipart.max-request-size=1024MB
4、编写controller:
final String fdfsWebServer = "http://localhost:8850/";
@ApiOperation("文件上传")
@Async("asyncServiceExecutor")
@PostMapping(value = {"/pt/fileserver/action/upload", "/pv/fileserver/action/upload"})
public Response<UploadResult> uploadFile(@RequestPart("file") MultipartFile file) {
try {
//上传
String fileUrlPath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), null).getFullPath();
UploadResult result = new UploadResult();
result.setOriginalFilename(file.getOriginalFilename());
result.setUrlPath(fdfsWebServer + fileUrlPath);
logger.info("文件上传成功:{}", result.toString());
return Response.returnObjectSuccess(result);
} catch (IOException e) {
logger.error("读取文件流失败:" + e.getMessage(), e);
throw new RuntimeException("读取文件流失败:" + e.getMessage(), e);
}
}
@ApiOperation("删除文件")
@DeleteMapping(value = {"/pt/fileserver/action/delete", "/pv/fileserver/action/delete"})
public Response<Boolean> deleteFile(@RequestParam("urlPath") String urlPath) {
//路径检查
String path = urlPath;
if (StringUtils.isEmpty(path)) {
logger.error("URL路径不能为空:" + path);
throw new RuntimeException("URL路径不能为空");
}
if (path.startsWith(fdfsWebServer)) {
path = path.substring(fdfsWebServer.length());
if (StringUtils.isEmpty(path)) {
logger.error("URL路径不合法:" + urlPath);
throw new RuntimeException("URL路径不合法");
}
}
fastFileStorageClient.deleteFile(path);
logger.info("删除文件{}成功", urlPath);
return Response.returnObjectSuccess(true);
}
5、上传文件代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title></head>
<body>
<form action="http://localhost:8820/fileserver/pb/fileserver/action/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" value="请选择文件">
<input type="submit" value="上传">
</form>
</body>
</html>
五、FastDFS清空数据及文件:
1、停止tracker、storage服务:
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf stop
/usr/bin/fdfs_storaged /etc/fdfs/storage-defaultgroup.conf stop
2、清空存储路径文件:
rm -rf /defaultgroup01/fastdfs/data/
3、清空tracker和storage的base_path:
rm -rf /data/fastdfs/tracker/data
rm -rf /data/fastdfs/tracker/logs
rm -rf /data/fastdfs/storage/defaultgroup/data
rm -rf /data/fastdfs/storage/defaultgroup/logs
4、启动tracker和storage服务:
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
/usr/bin/fdfs_storaged /etc/fdfs/storage-defaultgroup.conf start