分布式文件存储系统(fastdfs)

1、分布式文件存储系统

上传图片,由于有多台服务器,所以不能找到图片在哪台服务器上面,这时就需要一个文件服务器进行管理图片。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gnnnI9Sn-1585211003406)(assets/1584107074588.png)]

FastDFS就是一个文件服务器。

2、FastDFS

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kqxVUROV-1585211003408)(assets/1584855017183.png)]

1 支持上传-> 给我们返回一个路径

2 支持下载-> 使用路径下载

小文件分布式文件的存储系统

小于1 个G的文件都是小文件,就可以不用拆分该文件

大文件需要拆分。

FastDFS 就是一个分布式文件存储系统,由两部分组成。

1 tracker(跟踪器)

2 storage(存储器)

如果想扩充FastDFS的容量,非常方便,直接添加组就行了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KvsPRBdO-1585211003425)(assets/1584107517026.png)]

3、FastDFS的搭建

3.1、在服务器中创建FastDFS的容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s7sigUDQ-1585211003426)(assets/1584846243919.png)]

3.1.1、准备一个tracker

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

3.1.2、准备一个storage

1 公网地址 : 开发时,使用公网

2 私网地址: 服务上线,使用私网

docker run -d --name storage --net=host -e TRACKER_IP=服务器公网:22122 -e GROUP_NAME=g1 morunchang/fastdfs sh storage.sh

可以使用docker logs 容器名称命令进行查看容器是否运行成功。

位于同一组的storage中的文件会进行备份。

位于不同组可以使用负载均衡。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFrePqTe-1585211003427)(assets/1584108715256.png)]

3.2、添加项目依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b43sjZka-1585211003429)(assets/1584873611084.png)]

<!--spring boot项目导入的依赖-->
<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.26.7</version>
</dependency>
<!--测试类依赖-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

3.3、yml配置文件

fdfs:
  tracker-list:            #TrackerList参数,支持多个
  - 192.168.1.105:22122
  - 192.168.1.106:22122 

3.4、测试fastdfs的操作

package com.zxm.test;

import com.github.tobato.fastdfs.domain.fdfs.StorageNode;
import com.github.tobato.fastdfs.domain.fdfs.StorageNodeInfo;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadFileWriter;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.github.tobato.fastdfs.service.TrackerClient;
import com.zxm.utils.FastdfsUtil;
import lombok.SneakyThrows;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashSet;

@SpringBootTest
@RunWith(SpringRunner.class)
public class FileUploadTest {

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private TrackerClient trackerClient;

    /**
     * 文件的上传
     */
    @SneakyThrows
    @Test
    public void updateLoadTest(){
        // 也可以上传视频。只需要填入视频路径,然后将fileExtName换为视频的后缀就行。
        File file = new File("C:/Users/86131/Pictures/Saved Pictures/1.jpg");
        String path = fastFileStorageClient.uploadFile(
                new FileInputStream(file),
                file.length(),
                "jpg",
                new HashSet<>(0)).getFullPath();
        System.out.println(path);
    }

    /**
     * 文件的下载
     */
    @Test
    public void testDownload(){
        String path = "C:/Users/86131/Desktop/临时文件夹/d2.jpg";
        fastFileStorageClient.downloadFile("g1","M00/00/00/rBHR8l5h-T6AQTubAApSuL6VXKQ831.jpg", new DownloadFileWriter(path));
    }
    /**
     * 文件的删除
     * 删除之后,还可以访问,但是不能下载了。
     */
    @Test
    public void testDelete(){
        String fullPath = "g1/M00/00/00/rBHR8l5nSzeAS0pmAAVS7KokxMQ062.jpg";
        String groupName = FastdfsUtil.parseGroup(fullPath);
        System.out.println(groupName);
        String path = fullPath.replaceFirst(groupName+"/", "");
        System.out.println(path);
        fastFileStorageClient.deleteFile(groupName,path);
        System.out.println("删除完成");
//        或者直接使用下述方法就可删除。
//        fastFileStorageClient.deleteFile("g1","M00/00/00/rBHR8l5nSzeAS0pmAAVS7KokxMQ062.jpg");
    }

    @Test
    public void trackerTest(){
        /**
         * 文件下载时候用到。
         * fetchStorage对象中包含组名,storage的服务器ip,端口
         */
        StorageNodeInfo fetchStorage = trackerClient.getFetchStorage("g1", "M00/00/00/rBHR8l5nSzeAS0pmAAVS7KokxMQ062.jpg");
        /**
         * 文件上传时候用到
         * 得到当前注册到tracker上面的storege
         * 不同组可以使用负载均衡。
         */
        StorageNode storeStorage = trackerClient.getStoreStorage();
    }

}

3.5、应用fastDFS的controller

package com.zxm.controller;

import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * 负责文件上传的控制器
 */
@RestController
@RequestMapping("/admin/file")
public class FileController {
    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    // http://47.94.225.69:8080  fastDFS自定义地址配置。
    // 此处使用@Value注解从yml配置文件中注入。
    @Value("${resources.url}")
    private String serverAddress; 

    /**
     * 上传一个图片
     * @param file
     * @return
     */
    @SneakyThrows
    @PostMapping("/upload/element")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file){
        // 开始上传文件
        String fullPath = fastFileStorageClient.uploadFile(
                file.getInputStream(),
                file.getSize(),
                "jpg",
                null).getFullPath();
        return ResponseEntity.ok(serverAddress+"/"+fullPath);
    }
}
# fastdfs的自定义地址配置
resources:
  url: http://47.94.225.69:8080

4、 fastdfs的原理分析

4.1、fastDFS文件上传的流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-55GwGQnp-1585211003431)(assets/1584875740800.png)]

tracker还具有负载均衡的效果,从多个storage中选出一个进行操作。

4.2、fastDFS文件下载的流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TA857ey2-1585211003434)(assets/1584876101834.png)]

5、FastDFS和Nginx结合使用

5.1、对tracker做负载均衡

为了承载更高的并发量,tracker可以做成集群。需要使用nginx做负载均衡。

5.2、nginx插件fastdfs-nginx-module的作用

FastDFS通过Tracker服务器,将文件放在某个Storage服务器存储,但是同组Storage存储服务器之间需要进入文件复制,有同步延迟的问题

假设Tracker服务器将文件上传到了Storage Server 11,上传成功后文件ID已经返回给客户端。此时FastDFS存储集群机制会将这个文件同步到同组存储Storage Server 12,在文件还没有复制完成的情况下,客户端如果用这个文件ID在Storage Server 12上取文件,就会出现文件无法访问的错误。 (Storage Server 11和Storage Server 12是同一个storage组)

,但是同组Storage存储服务器之间需要进入文件复制,有同步延迟的问题

假设Tracker服务器将文件上传到了Storage Server 11,上传成功后文件ID已经返回给客户端。此时FastDFS存储集群机制会将这个文件同步到同组存储Storage Server 12,在文件还没有复制完成的情况下,客户端如果用这个文件ID在Storage Server 12上取文件,就会出现文件无法访问的错误。 (Storage Server 11和Storage Server 12是同一个storage组)

fastdfs-nginx-module可以重定向文件连接到文件上传时的源服务器(Storage Server 11)取文件,避免客户端由于复制延迟导致的文件无法访问错误 。

发布了29 篇原创文章 · 获赞 0 · 访问量 2248

猜你喜欢

转载自blog.csdn.net/rootDream/article/details/105121617