FastDFS体验

38 阅读5分钟

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”后就一切正常了。

image.png

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