栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

FastDFS

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

FastDFS

FastDFS 一、概述 (一)分布式文件系统
  • 分布式文件系统 (Distributed File System) 是一个软件/软件服务器,这个软件可以用来管理文件。
  • 这个软件所管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上,这些服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件系统来管理这些服务器上的文件。
  • 常见的分布式文件系统有:FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS等。

  • 传统方式弊端:
    • 如果用户数量多,IO操作比较多,对磁盘访问压力很大
    • 如果磁盘发生故障,会造成数据丢失
    • 存储容量有限
(二)FastDFS 1、简介
  • FastDFS是一个开源的轻量级分布式文件系统,为互联网应用量身定做,简单、灵活、高效
  • 采用C语言开发,由阿里巴巴开发并开源。
  • FastDFS对文件进行管理,功能包括:
    • 文件存储、文件同步、文件访问(文件上传、文件下载、文件删除)等,
    • 解决了大容量文件存储的问题,
    • 特别适合以文件为载体的在线服务,如相册网站、文档网站、图片网站、视频网站等等。
  • FastDFS充分考虑了冗余备份、线性扩容等机制,并注重高可用、高性能等指标
  • 使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
  • FastDFS代码托管在github上:https://github.com/happyfish100/fastdfs
2、整体架构
  • FastDFS文件系统由两大部分构成,一个是客户端,一个是服务端
    • 客户端通常指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端
    • 服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)
      • 跟踪器(tracker)主要做调度工作,在内存中记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽。因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。
      • 存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。
3、安装 (1)安装前的准备
  • 检查Linux上是否安装了 gcc、libevent、libevent-devel,没有安装需进行安装(yum install gcc libevent libevent-devel -y)
  • 安装 libfastcommon 库(libfastcommon 库是 FastDFS 文件系统运行需要的公共 C 语言函数库):
    • 解压下载下来的tar.gz压缩包到当前目录——tar -zxvf libfastcommon-1.0.36.tar.gz
    • 切换到解压后的libfastcommon目录——cd libfastcommon-1.0.36
    • 执行make脚本进行编译——./make.sh
    • 执行make install进行安装——./make.sh install
(2)安装FastDFS
  • FastDFS没有Windows版本,不能在Windows下使用,FastDFS需要安装部署在Linux环境下
  • 解压下载下来的tar.gz压缩包到当前目录——tar -zxvf fastdfs-5.11.tar.gz
  • 切换到解压后FastDFS的目录
  • 执行make脚本进行编译——./make.sh
  • 执行make install进行安装——./make.sh install
4、FastDFS启动 (1)启动
  • FastDFS服务启动需要启动两个脚本:
    • 在任意目录下执行:fdfs_trackerd /etc/fdfs/tracker.conf
    • 在任意目录下执行:fdfs_storaged /etc/fdfs/storage.conf
(2)重启
  • fdfs_trackerd /etc/fdfs/tracker.conf restart
(3)关闭
  • 在任意目录下执行:fdfs_trackerd /etc/fdfs/tracker.conf stop
(4)注意
  • 没有搭建集群默认只有一个组group1
  • 后缀名包含-m的为属性文件(meta)
  • 在Linux中并没有磁盘一说,是虚拟的

二、分布式文件系统FastDFS的HTTP访问
  • FastDFS提供了一个Nginx扩展模块,利用该模块,我们可以通过Nginx访问已经上传到FastDFS上的文件
(一)准备
  • 将Fastdfs的Nginx扩展模块源代码上传到Linux上

  • 解压下载下来的fastdfs-nginx-module-master.zip 文件——unzip fastdfs-nginx-module-master.zip

  • 切换至解压后的Nginx主目录,执行配置操作

    • cd nginx-1.14.2
    • ./configure --prefix=/usr/local/nginx_fdfs --add-module=/home/soft/fastdfs-nginx-module-master/src
      • –prefix是指定nginx安装路径
      • –add-module指定fastDFS的nginx模块的源代码路径
  • 执行命令进行编译——make

  • 执行命令进行安装——make install

  • 将/home/soft/fastdfs-nginx-module-master/src(自己实际存放Nginx扩展模块的目录)目录下的mod_fastdfs.conf文件拷贝到 /etc/fdfs/目录下,这样才能正常启动Nginx

    • cp /home/soft/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
  • 修改mod_fastdfs.conf配置文件

    • base_path=/opt/fastdfs/nginx_mod
    • tracker_server=192.168.235.128:22122
    • url_have_group_name = true
    • store_path0=/opt/fastdfs/storage/files
  • 配置Nginx的配置文件:

    • #拦截请求路径中包含 /group[1-9]/M0[0-9] 的请求,用 fastdfs的Nginx 模块进行转发
    location ~ /group[1-9]/M0[0-9] {	
    
       ngx_fastdfs_module; 
    
    }
    
    //ngx_fastdfs_module;  #这个指令不是Nginx本身提供的,是扩展模块提供的,根据这个指令找到FastDFS提供的Nginx模块配置文件,然后找到Tracker,最终找到Stroager
    
(二)原理


三、FastDFS在Java项目中开发示例
  • 在实际项目开发中,FastDFS提供的主要功能:
    • upload:上传文件
    • download:下载文件
    • delete:删除文件
  • FastDFS文件系统的Java客户端是指采用Java语言编写的一套程序,专门用来访问fastDFS文件系统,其实就是一个jar包。
(一)文件上传
  • 在pom.xml文件中添加FastDFS本地仓库的jar包(FastDFS的java客户端依赖)

     org.csource
     fastdfs-client-java
     1.27-SNAPSHOT

  • resources目录下,在里面主要配置tracker地址:
tracker_server=192.168.42.128:22122
  • 代码
    public static void upload(){

        TrackerServer ts = null;
        StorageServer ss = null;

        try {

            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc = new TrackerClient();
            ts = tc.getConnection();
            ss = tc.getStoreStorage(ts);

            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
            StorageClient sc = new StorageClient(ts,ss);

            
            String[] result = sc.upload_file("d:/1.jpg","jpg",null);
            for(String str : result){
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }finally{
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ts != null) {
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
(二)文件下载
 
    public static void download(){

        TrackerServer ts = null;
        StorageServer ss = null;

        try {

            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc = new TrackerClient();
            ts = tc.getConnection();
            ss = tc.getStoreStorage(ts);

            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
            StorageClient sc = new StorageClient(ts,ss);

            
            String group = "group1";
            String fileName = "M00/00/00/wKgqgGJ-BbyAVOM9ABKAocfYGyk468.jpg";
            int result = sc.download_file(group,fileName,"d:/2.jpg");
            System.out.println(result);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }finally{
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ts != null) {
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
  • 返回值为0表示下载成功,其他数字均为下载失败
(三)文件删除
    public static void delete(){
        TrackerServer ts = null;
        StorageServer ss = null;

        try {

            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc = new TrackerClient();
            ts = tc.getConnection();
            ss = tc.getStoreStorage(ts);

            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
            StorageClient sc = new StorageClient(ts,ss);

            
            String group = "group1";
            String fileName = "M00/00/00/wKgqgGJ-BbyAVOM9ABKAocfYGyk468.jpg";
            int result = sc.delete_file(group,fileName);
            System.out.println(result);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }finally{
            if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ts != null) {
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
(四)改造
  • 因为使用FastDFS进行文件操作代码大多都是通用的,所以我们这里在FastDFS类中将通用的功能进行封装,并提供上传、下载、删除文件的方法
  • 注意:这里只是简单的封装,如果多线程会有问题
1、抽取获取StorageClient的方法
public static StorageClient getStorageClient() throws IOException, MyException {
    //1.加载配置文件,默认去classpath下加载
    ClientGlobal.init("fdfs_client.conf");
    //2.创建TrackerClient对象
    TrackerClient trackerClient = new TrackerClient();
    //3.创建TrackerServer对象
    trackerServer = trackerClient.getConnection();
    //4.创建StorageServler对象
    storageServer = trackerClient.getStoreStorage(trackerServer);
    //5.创建StorageClient对象,这个对象完成对文件的操作
    StorageClient storageClient = new StorageClient(trackerServer,storageServer);
    return storageClient;
}
2、定义两个全局变量
private static TrackerServer trackerServer = null;
private static StorageServer storageServer = null;
3、抽取关闭资源的方法
public static void closeFastDFS() {
    if (storageServer != null) {
        try {
            storageServer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if (trackerServer != null) {
        try {
            trackerServer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
4、改造文件上传的方法
public static void fileUpload(){
    try {
        //1. 获取StorageClient对象
        StorageClient storageClient = getStorageClient();
        //2.上传文件  第一个参数:本地文件路径 第二个参数:上传文件的后缀 第三个参数:文件信息
        String [] uploadArray = storageClient.upload_file("D:/aa.txt","txt",null);
        for (String str:uploadArray) {
            System.out.println(str);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (MyException e) {
        e.printStackTrace();
    } finally {
        closeFastDFS();
    }
}
5、下载文件
//下载文件的方法
public static void fileDownload(){
    try {
        //1. 获取StorageClient对象
        StorageClient storageClient = getStorageClient();
        //2.下载文件 返回0表示成功,其它均表示失败
        int num = storageClient.download_file("group1",
                "M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt","E:/bb.txt");
        System.out.println(num);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (MyException e) {
        e.printStackTrace();
    } finally {
        closeFastDFS();
    }
}
6、删除文件
//删除文件的方法
public static void fileDelete(){
    try {
        //1. 获取StorageClient对象
        StorageClient storageClient = getStorageClient();
        //2.删除文件 返回0表示成功,其它均表示失败
        int num = storageClient.delete_file("group1",
                "M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt");
        System.out.println(num);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (MyException e) {
        e.printStackTrace();
    } finally {
        closeFastDFS();
    }

四、FastDFS在web项目中的应用
  • 对P2P项目合同进行管理,在WEB项目中实现对文件的上传下载和删除操作
  • 债权是债务的对应词,但是在P2P项目中,我们管理的债权,以及合同一般指的是借款人的信息,所以在我们下面创建的creditor_info表中存的是借款人信息
  • 合同是pdf文件
(一)环境搭建 1、创建数据库
  • 创建表
CREATE TABLE `creditor_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`realName` varchar(35) DEFAULT NULL COMMENT '债权借款人姓名',
`idCard` varchar(18) DEFAULT NULL COMMENT '债权借款人身份证',
`address` varchar(150) DEFAULT NULL COMMENT '债权借款人地址',
`sex` int(1) DEFAULT NULL COMMENT '1男2女',
`phone` varchar(11) DEFAULT NULL COMMENT '债权借款人电话',
`money` decimal(10,2) DEFAULT NULL COMMENT '债权借款人借款金额',
`groupName` varchar(10) DEFAULT NULL COMMENT '债权合同所在组',
`remoteFilePath` varchar(150) DEFAULT NULL COMMENT '债权合同所在路径',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2、开发环境搭建 (1)创建springboot工程
  • 添加spring依赖
  • 添加mybatis依赖
  • 添加web依赖
  • 添加Thymeleaf依赖
  • 添加MySQL依赖
(2)配置数据库信息
#数据库的连接配置信息
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.235.128:3306/fastdfs?useUnicode=true&characterEncoding=utf8&useSSL=false

#开发阶段,建议关闭thymeleaf的缓存,不然没有办法看到实时页面
spring.thymeleaf.cache=false
#去掉HTML5的语法验证
spring.thymeleaf.mode=LEGACYHTML5

#设置SpringMVC允许上传的单个文件大小 默认值为 1M
#spring.servlet.multipart.max-file-size=1M
#设置SpringMVC允许的表单请求中上传文件总大小 默认为 10M
#spring.servlet.multipart.max-request-size=10M
  • 指定编译位置以及添加mybatis逆向工程

        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
                org.mybatis.generator
                mybatis-generator-maven-plugin
                1.3.6
                
                    
                    GeneratorMapper.xml
                    true
                    true
                
            
        
        
            
                src/main/java
                
                    **
    @PostMapping("/upload")
    public String upload(Integer id, MultipartFile myFile, Model model) throws IOException {
//        System.out.println(myFile.getBytes());//获取文件对应字节数组
//        System.out.println(myFile.getInputStream());//获取文件对应的输入流
//        System.out.println(myFile.getContentType());//获取文件类型
//        System.out.println(myFile.getName());//获取表单元素名
//        System.out.println(myFile.getOriginalFilename());//获取文件名
//        System.out.println(myFile.getSize());//获取文件大小
//        System.out.println(myFile.isEmpty());//判断文件是否为空 如果没有上传文件或文件大小为0 这个值都是true

//收集用户请求信息,即上传的文件数据
        //获取文件对应的字节数组
        byte[] buffFile = myFile.getBytes();
        //获取文件名
        String fileName = myFile.getOriginalFilename();
        Long fileSize = myFile.getSize();
        String fileType = myFile.getContentType();
        //可能会出现问题因为有些文件可能没有扩展名,因此必要时需要做逻辑控制
        String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1);
//调用工具类
        String[] result = FastDFSUtil.upload(buffFile,fileExtName);
        
        CreditorInfo creditorInfo=new CreditorInfo();
        creditorInfo.setId(id);
        creditorInfo.setFileSize(fileSize);
        creditorInfo.setFileType(fileType);
        creditorInfo.setOldFilename(fileName);
        creditorInfo.setGroupName(result[0]);
        creditorInfo.setRemoteFilePath(result[1]);
        
        creditorService.updateFileInfo(creditorInfo);
        
        model.addAttribute("message","文件上传成功,点击确定返回列表页面!");
        model.addAttribute("url","/");
        return "success";
    }
  • 工具类
public class FastDFSUtil {


    
    public static String [] upload(byte[] buffFile,String fileExtName) {
        TrackerServer ts=null;
        StorageServer ss=null;
        try {
            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc=new TrackerClient();
            ts=tc.getConnection();
            ss=tc.getStoreStorage(ts);
            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
            StorageClient sc=new StorageClient(ts,ss);
            
            String[] result= sc.upload_file(buffFile,fileExtName,null);

            return result;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        } finally {
            if(ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    
    public static byte [] download(String groupName,String remoteFilename) {
        TrackerServer ts=null;
        StorageServer ss=null;
        try {
            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc=new TrackerClient();
            ts=tc.getConnection();
            ss=tc.getStoreStorage(ts);
            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
            StorageClient sc=new StorageClient(ts,ss);
            

            byte [] buffFile=sc.download_file(groupName,remoteFilename);
            return buffFile;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        } finally {
            if(ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    
    public static void delete(String groupName,String remoteFilename) {
        TrackerServer ts=null;
        StorageServer ss=null;
        try {
            //读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
            ClientGlobal.init("fastdfs.conf");
            TrackerClient tc=new TrackerClient();
            ts=tc.getConnection();
            ss=tc.getStoreStorage(ts);
            //定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
            StorageClient sc=new StorageClient(ts,ss);
            
            int result=sc.delete_file(groupName,remoteFilename);
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        } finally {
            if(ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
service
@Override
    public CreditorInfo selectById(Integer id) {
        return creditorInfoMapper.selectByPrimaryKey(id);
    }
@Override
    public void updateFileInfo(CreditorInfo creditorInfo) {
        creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo);
    }
Dao层