FastDFS

FastDFS

一、FastDFS概述

1. 常见的分布式文件系统对比

  • HDFS(Hadoop Distributed File System)和GFS(Google File System)是通用的分布式文件系统,它们的优点是开发体验好;缺点是系统的复杂度较高,性能也一般,需要将一个文件分割成n份存储在不同的节点上

  • FastDFS是专用的分布式文件系统,它的优点是复杂度低,性能较高,适合存储图片、小视频等小文件,因为FastDFS对文件是不分割的,所以没有文件合并的开销;缺点是开发体验一般

2. FastDFS组成概述

  • 主要组成

    • Tracker Server

      Tracker Server作用:负载均衡和调度,管理Storage Server

      Tracker Server可以集群,实现高可用,策略为轮询

    • Storage Server

      Storage Server作用:文件存储

      Storage Server集群采用分组的方式,同组内的每台服务器是平等关系、数据同步,目的是实现数据备份,从而高可用,而不同组的服务器之间是不通信的

      Storage Server会连接Tracker Server集群中的所有节点,定时向它们发送自身状态

      (剩余空间,文件同步情况,文件上传下载次数等信息),方便Tracker Server调度

  • 工作流程

    1. Storage定时向Tracker上传状态信息

    2. 当Client上传连接请求到Tracker时,Tracker查询可用的Storage向Client返回信息(Storage的IP和端口)

    3. 上传和下载(需要Client与Tracker连接)

      • 上传:Client直接向Storage发送file content和metadata,Storage生成file_id并将文件写入磁盘,最后Storage向Client返回file_id(包含路径信息和文件名)

      • 下载:Client直接向Storage发送file_id(包含组名、路径和文件名),Storage查找文件后将file_content返回给Client

        file_id格式:组名(Storage Server)/虚拟磁盘路径(M00或M01)/数据两级目录(虚拟磁盘自行创建)/文件名

二、FastDFS使用方式

1. 启动服务

  • 启动tracker(需要同时启动tracker和storage)

    /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
    
  • 启动storage(需要同时启动tracker和storage)

    /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
    
  • 查看所有运行的端口

    netstat -ntlp
    
  • 上传文件前关闭防火墙

    systemctl stop firewalld.service
    

三、FastDFS API

1. 实现文件上传

  • 示例Code

    当Storage单机存在时,组名为group1;

    上传后的文件在/etc/fdfs中的storage.confstore_path0对应的路径下data中,data文件夹下也叫虚拟磁盘路径

    public class TestUpload {
        public static void main(String[] args) {
            try {
                // 加载配置文件
                ClientGlobal.initByProperties("config/fastdfs-client.properties");
                // 创建tracker客户端
                TrackerClient trackerClient = new TrackerClient();
                // 通过tracker客户端获取连接服务并返回
                TrackerServer trackerServer = trackerClient.getConnection();
                // 声明storage服务
                StorageServer storageServer = null;
                // 定义storage客户端
                StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
    
                // 定义文件元信息
                NameValuePair[] array = new NameValuePair[1];
                array[0] = new NameValuePair("filename", "img01.png");
                // 文件上传成功后会返回fileId
                String fileId = storageClient1.upload_file1("D:\\upload\\img01.png", "png", array);
                System.out.println("fileId = " + fileId);
    
                // 关闭连接
                trackerServer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /*
    fileId = group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png
    */
    

2. 实现文件查询

  • 示例Code

    public class TestQuery {
        public static void main(String[] args) {
            try {
                // 加载配置文件
                ClientGlobal.initByProperties("config/fastdfs-client.properties");
                // 创建tracker客户端
                TrackerClient trackerClient = new TrackerClient();
                // 通过tracker客户端获取连接服务并返回
                TrackerServer trackerServer = trackerClient.getConnection();
                // 声明storage服务
                StorageServer storageServer = null;
                // 定义storage客户端
                StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
    
                // 查询文件信息
                FileInfo fileInfo = storageClient1.query_file_info1("group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png");
                if (fileInfo != null) {
                    System.out.println("fileInfo" + fileInfo);
                } else {
                    System.out.println("The file does not exist");
                }
    
                // 关闭连接
                trackerServer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /*
    fileInfosource_ip_addr = 192.168.197.128, file_size = 46261, create_timestamp = 2022-04-18 23:56:29, crc32 = -1383628569
    */
    

3. 实现文件下载

  • 示例Code

    public class TestDownload {
        public static void main(String[] args) {
            try {
                // 加载配置文件
                ClientGlobal.initByProperties("config/fastdfs-client.properties");
                // 创建tracker客户端
                TrackerClient trackerClient = new TrackerClient();
                // 通过tracker客户端获取连接服务并返回
                TrackerServer trackerServer = trackerClient.getConnection();
                // 声明storage服务
                StorageServer storageServer = null;
                // 定义storage客户端
                StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
    
                // 下载指定file_id的文件,通过字节输出流写入文件
                byte[] array = storageClient1.download_file1("group1/M00/00/00/wKjFgGJdii2AcVIHAAC0ta2HgOc915.png");
                FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\upload\\testdownload01.png"));
                fileOutputStream.write(array);
                fileOutputStream.close();
                System.out.println("succeed to download file");
    
                // 关闭连接
                trackerServer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /*
    succeed to download file
    */
    

四、图片/视频服务器案例

  • 主要流程

    需要配置图片服务器:安装fastdfs-nginx-module,配置nginx.conf

    server {
        listen       81;
        server_name  192.168.197.128;
    
        location /group1/M00 {
            root /home/fastdfs/fdfs_storage/data;
            ngx_fastdfs_module;
        }
    }
    

    浏览器访问server_name与监听的端口号,可查看nginx欢迎页面

    浏览器访问server_name与监听的端口号+fileId,可查看图片/视频服务器上存储的指定文件

  • 示例Code

    将文件上传到web服务器上,将web服务器上存储的文件上传到FastDFS

    @Controller
    public class FileAction {
    
        @RequestMapping("upload")
        @ResponseBody
        public FileSystem upload(MultipartHttpServletRequest request) throws Exception {
            FileSystem fileSystem = new FileSystem();
    
            /* 1. 将文件上传到web服务器上 */
            // 从页面的请求中, 获取上传的文件对象
            MultipartFile file = request.getFile("fname");
            // 获取文件的原始文件名,并获取文件的扩展名,将UUID作为新上传文件的文件名
            String originalFilename = file.getOriginalFilename();
            String fileTypeName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            String newFileName = UUID.randomUUID().toString() + "." + fileTypeName;
            // 将路径转换成文件
            File toSaveFile = new File("D:/upload/" + newFileName);
            file.transferTo(toSaveFile);
    
            /* 2. 将文件上传到FastDFS */
            // 加载配置文件
            ClientGlobal.initByProperties("config/fastdfs-client.properties");
            // 创建tracker客户端
            TrackerClient trackerClient = new TrackerClient();
            // 通过tracker客户端获取连接服务并返回
            TrackerServer trackerServer = trackerClient.getConnection();
            // 声明storage服务
            StorageServer storageServer = null;
            // 定义storage客户端
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
    
            // 定义文件元信息
            NameValuePair[] array = new NameValuePair[1];
            array[0] = new NameValuePair("filename", originalFilename);
            // 文件上传成功后会返回fileId
            String fileId = storageClient1.upload_file1(toSaveFile.getAbsolutePath(), fileTypeName, array);
            System.out.println("fileId = " + fileId);
            // 关闭连接
            trackerServer.close();
    
            // 封装fileSystem对象
            fileSystem.setFileId(fileId);
            fileSystem.setFileName(originalFilename);
            fileSystem.setFilePath(fileId);
    
            return fileSystem;
        }
    }
    
posted @   Ramentherapy  阅读(138)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示