其他分享
首页 > 其他分享> > 分布式文件系统—FastDFS

分布式文件系统—FastDFS

作者:互联网

1.场景概述

天猫,淘宝等购物网站,大量的图片和视频,文件太多,如何存储?
用户访问量大又如何保证下载速度?分布式文件系统就是解决这些问题的!

1.1 什么是文件系统

文件数据是如何存储的??

image-20220108200336759

image-20220108200346232

1.2 分布式文件系统

1.3 主流的分布式文件系统

1.3.1 HDFS

1.3.2 GFS

1.3.3.FastDFS

image-20220108200624326

1.4 工作原理

image-20220108200720407

1.5 上传/下载 原理

image-20220126151517149

image-20220126151537948

2.FastDFS的上传与下载

2.1 安装

2.1.1 安装gcc(编译时需要)

yum install -y gcc gcc-c++

2.1.2 安装libevent(运行时需求)

yum -y install libevent

2.1.3 安装 libfastcommon

libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS运行所需要的一些基础库。

  1. 上传 libfastcommon-master.zip 到 /opt
安装解压zip包的命令:  yum install -y unzip
解压包:             unzip libfastcommon.zip
进入目录:           cd libfastcommon-master
  1. 编译
./make.sh
chmod 777 make.sh
  1. 安装
./make.sh install
  1. 拷贝库文件
cd /usr/lib64
cp libfastcommon.so /usr/lib

2.1.4 安装Tracker

下载 FastDFS_v5.05.tar.gz,并上传到 /opt

tar -zxvf FastDFS_v5.05.tar.gz
cd FastDFS
./make.sh
./make.sh install

安装成功将安装目录下的conf下的文件拷贝到/etc/fdfs/下

cp /opt/FastDFS/conf/* /etc/fdfs/

2.2 配置

vim /etc/fdfs/tracker.conf
#端口号
port=22122   
#基础目录(Tracker运行时会向此目录存储storage的管理数据)(基础目录不存在的话,需要自行创建 
mkdir /home/fastdfs)
base_path=/home/fastdfs 
vim /etc/fdfs/storage.conf
#配置组名
group_name=group1
#端口
port=23000
#向tracker心跳间隔(秒)
heart_beat_interval=30
#storage基础目录
#目录不存在,需要自行创建
base_path=/home/fastdfs
#store存放文件的位置(store_path)
#可以理解一个磁盘一个path,多个磁盘,多个store_path
#fdfs_storage目录不存在,需要自行创建
#mkdir /home/fastdfs/fdfs_storage
store_path0=/home/fastdfs/fdfs_storage 
#如果有多个挂载磁盘则定义多个store_path,如下
#store_path1=.....   (M01)
#store_path2=.....   (M02)

#配置tracker服务器:IP
tracker_server=10.1.220.247:22122
#如果有多个则配置多个tracker
#tracker_server=10.1.220.x:22122

2.3 启动服务

/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
netstat -ntlp

2.4 搭建 Java工程

使用IDEA创建maven工程

2.4.1 pom.xml

<!--fastdfs的java客户端-->
<dependency>
    <groupId>net.oschina.zcx7878</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.27.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

2.4.2 创建配置文件

在resources下创建config目录,在config目录下创建 fastdfs-client.properties,内容如下:

##fastdfs-client.properties
fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80
fastdfs.tracker_servers = 10.1.220.247:22122

2.4.3 文件上传

package test;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
/**
 * @BelongsProject: lagou-fastdfs
 * @Author: GuoAn.Sun
 * @CreateTime: 2020-07-28 17:33
 * @Description: 文件上传
 */
public class TestUpload {
    public static void main(String[] args) {
        try {
            // 加载配置文件
            ClientGlobal.initByProperties("config/fastdfs-client.properties");
            // 创建tracker客户端
            TrackerClient trackerClient = new TrackerClient();
            // 通过tracker客户端获取tracker的连接服务并返回
            TrackerServer trackerServer = trackerClient.getConnection();
            // 声明storage服务
            StorageServer storageServer = null;
            // 定义storage客户端
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);
            // 定义文件元信息
            NameValuePair[] list = new NameValuePair[1];
            list[0] = new NameValuePair("fileName","1.jpg");
            String fileID = client.upload_file1("F:\\img\\1.jpg", "jpg", list);
            System.out.println("fileID = " + fileID);
            // group1/M00/00/00/CgHc918f8l6AFYp0AAWICfQnHuk889.jpg
            /*
            group1:一台服务器,就是一个组
            M00: store_path0 ----> /home/fastdfs/fdfs_storage/data
            00/00:两级数据目录
             */
            trackerServer.close();
        }catch(Exception e){
            e.printStackTrace();
            }
    }
}

2.4.4 文件查询

package test;
import org.csource.fastdfs.*;
/**
 * @BelongsProject: lagou-fastdfs
 * @Author: GuoAn.Sun
 * @CreateTime: 2020-07-28 17:46
 * @Description: 文件查询
 */
public class TestQuery {
    public static void main(String[] args) throws Exception {
        // 加载配置文件
        ClientGlobal.initByProperties("config/fastdfs-client.properties");
        // 创建tracker客户端
        TrackerClient trackerClient = new TrackerClient();
        // 通过tracker客户端获取tracker的连接服务并返回
        TrackerServer trackerServer = trackerClient.getConnection();
        // 声明storage服务
        StorageServer storageServer = null;
        // 定义storage客户端
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        FileInfo fileInfo = client.query_file_info1("group1/M00/00/00/CgHc918f8l6AFYp0AAWICfQnHuk889.jpg");
        if(fileInfo!=null)
            System.out.println("fileInfo = " + fileInfo);
        else
            System.out.println("查无此文件!");
        trackerServer.close();
    }
}

2.4.5 文件下载

package test;
import org.csource.fastdfs.*;
import java.io.File;
import java.io.FileOutputStream;
/**
 * @BelongsProject: lagou-fastdfs
 * @Author: GuoAn.Sun
 * @CreateTime: 2020-07-28 17:49
 * @Description: 文件下载
 */
public class TestDownload {
    public static void main(String[] args) throws Exception{
        // 加载配置文件
        ClientGlobal.initByProperties("config/fastdfs-client.properties");
        // 创建tracker客户端
        TrackerClient trackerClient = new TrackerClient();
        // 通过tracker客户端获取tracker的连接服务并返回
        TrackerServer trackerServer = trackerClient.getConnection();
        // 声明storage服务
        StorageServer storageServer = null;
        // 定义storage客户端
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        byte[] bytes = client.download_file1("group1/M00/00/00/CgHc918f8l6AFYp0AAWICfQnHuk889.jpg");
        // 通过io将字节数组,转换成一个文件
        FileOutputStream fileOutputStream = new FileOutputStream(new File("F:/xxxxxx.jpg"));
        fileOutputStream.write(bytes);
        fileOutputStream.close();
        trackerServer.close();
        System.out.println("下载完毕!");
    }
}

3.项目实战

3.1 搭建图片服务器

3.1.1 Nginx模块安装 (Storage)

  1. 上传 fastdfs-nginx-module_v1.16.tar.gz 到 /opt
  2. 解压nginx模块
tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
  1. 修改 config 文件,将文件中的 /usr/local/ 路径改为 /usr/
cd /opt/fastdfs-nginx-module/src
vim config
  1. 将 fastdfs-nginx-module/src下的 mod_fastdfs.conf 拷贝至 /etc/fdfs 下
cp mod_fastdfs.conf /etc/fdfs/
  1. 修改 /etc/fdfs/mod_fastdfs.conf
vim /etc/fdfs/mod_fastdfs.conf
base_path=/home/fastdfs
tracker_server=10.1.220.247:22122 
#(n个tracker配置n行)
#tracker_server=10.1.220.x:22122
#url中包含group名称
url_have_group_name=true       
#指定文件存储路径(上面配置的store路径) 
store_path0=/home/fastdfs/fdfs_storage 
  1. 将 libfdfsclient.so 拷贝至 /usr/lib 下
cp /usr/lib64/libfdfsclient.so /usr/lib/
  1. 创建nginx/client目录
mkdir -p /var/temp/nginx/client

3.1.2 Nginx安装 (Tracker)

  1. 将 nginx-1.14.0.tar.gz上传到/opt(安装过nginx,此步省略)
  2. 解压:tar -zxvf nginx-1.14.0.tar.gz(安装过nginx,此步省略)
  3. 安装依赖库(安装过nginx,此步省略)
yum install pcre
yum install pcre-devel
yum install zlib
yum install zlib-devel
yum install openssl
yum install openssl-devel
  1. 进入nginx解压的目录下 cd /opt/nginx-1.14.0
  2. 安装
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/opt/fastdfs-nginx-module/src

注意:上边将临时文件目录指定为 /var/temp/nginx,需要在 /var 下创建 temp 及 nginx 目录:mkdir /var/temp/nginx

  1. 编译:make
  2. 安装:make install
  3. 拷贝配置文件
cd /opt/FastDFS/conf
cp http.conf mime.types /etc/fdfs/
是否覆盖:yes
  1. 修改nginx配置文件
cd /usr/local/nginx/conf/
vim nginx.conf
server {
    listen       80;
    server_name  10.1.220.247;
    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    location /group1/M00 {
        root   /home/fastdfs/fdfs_storage/data;
        ngx_fastdfs_module;
    }
  1. 关闭nginx,并启动nginx
pkill -9 nginx
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
  1. 访问nginx并查看图片
    http://10.1.220.247
    http://10.1.220.247/group1/M00/00/00/CgHc918f8l6AFYp0AAWICfQnHuk889.jpg

3.2 创建前端页面

<%--上传文件,文件与文字相比较起来,属于内容较大,必须使用post方式提交--%>
<%--上传文件,和普通文件有区别,action接收参数也会区别对待,所以声明带文件提交的表单为“多部
件表单”--%>
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="fname">
    <br>
    <button>提交</button>
</form>

3.3 搭建web服务

3.3.1 pom.xml

<packaging>war</packaging>
<dependencies>
    <!-- 因为有jsp页面,所以引用servlet依赖-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <scope>provided</scope>
        <version>2.5</version>
    </dependency>
    <!-- 页面提交过来的请求,使用springmvc来处理-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
    <!-- java连接fastDFS的客户端工具-->
    <dependency>
        <groupId>net.oschina.zcx7878</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27.0.0</version>
    </dependency>
    <!-- 图片上传到FastDFS需要用的到IO工具-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!-- 图片保存到web服务器需要用到的IO工具-->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    <!--用来转换java对象和json字符串,注意,2.7以上版本必须搭配spring5.0以上-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <configuration>
                <port>8001</port>
                <path>/</path>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3.3.2 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

3.3.3 spring-mvc.xml

<!--扫描注解的包-->
<context:component-scan base-package="controller"/>
<!--扫描控制器中的注解:@Response-->
<mvc:annotation-driven/>
<!--上传文件的解析器(规定上传文件的大小限制)-->
<bean id="multipartResolver" 
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 上传文件最大限制:2GB-->
    <property name="maxUploadSize" value="2048000000"/>
</bean>

3.3.4 文件实体类

public class FileSystem implements Serializable {
    private String fileId;
    private String filePath;
    private String fileName;
}

3.3.5 控制层

package controller;
import entity.FileSystem;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.File;
import java.util.UUID;
/**
 * @BelongsProject: lagou-imageServer
 * @Author: GuoAn.Sun
 * @CreateTime: 2020-07-29 14:25
 * @Description: 处理上传文件的控制器
 */
@Controller
public class FileAction {
    /**
     * @param request 多部件表单的请求对象
     * @return 上传文件对象的json对象
     * @throws Exception
     *
     * 上传文件的流程:
     * 1、先把文件保存到web服务器上
     * 2、再从web服务器上将文件 上传 到 FastDFS上
     */
    @RequestMapping("upload")
    //MultipartHttpServletRequest:是httpservletRequest的强化版本,不仅可以装文本信息,还可以装图片文件信息
    public @ResponseBody FileSystem upload(MultipartHttpServletRequest request) 
throws Exception {
        FileSystem fileSystem = new FileSystem();
        /* 1、把文件保存到web服务器*/
        // 从页面请求中,获取上传的文件对象
        MultipartFile file = request.getFile("fname");
        // 从文件对象中获取 文件的原始名称
        String oldFileName = file.getOriginalFilename();
        // 通过字符串截取的方式,从文件原始名中获取文件的后缀   1.jpg
        String hou = oldFileName.substring(oldFileName.lastIndexOf(".") + 1);
        // 为了避免文件因为同名而覆盖,生成全新的文件名
        String newFileName = UUID.randomUUID().toString() + "." + hou;
        // 创建web服务器保存文件的目录(预先创建好D:/upload目录,否则系统找不到路径,会抛异常)
        File toSaveFile = new File("D:/upload/" + newFileName);
        // 将路径转换成文件
        file.transferTo(toSaveFile);
        // 获取服务器的绝对路径
        String newFilePath = toSaveFile.getAbsolutePath();
        /* 2、把文件从web服务器上传到FastDFS*/
        ClientGlobal.initByProperties("config/fastdfs-client.properties");
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        StorageServer storageServer = null;
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        NameValuePair[] list = new NameValuePair[1];
        list[0] = new NameValuePair("fileName",oldFileName);
        String fileId = client.upload_file1(newFilePath, hou, list);
        trackerServer.close();
        // 封装fileSystem数据对象
        fileSystem.setFileId(fileId);
        fileSystem.setFileName(oldFileName);
        fileSystem.setFilePath(fileId);  //已经上传到FastDFS上,通过fileId来访问图片,所以fileId即为文件路径
        return  fileSystem;
    }
}

3.3.6 添加fastDFS的配置文件

在resources下创建config目录,在config目录下创建 fastdfs-client.properties
参考:2.4.2

3.3.7 启动fastDFS服务,测试开始

[root@localhost /]# /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
[root@localhost /]# /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
[root@localhost /]# /usr/local/nginx/sbin/nginx -c 
/usr/local/nginx/conf/nginx.conf
[root@localhost /]# netstat -ntlp
[root@localhost /]# systemctl stop firewalld.service
[root@localhost /]# cd /home/fastdfs/fdfs_storage/data/
[root@localhost /]# ls

3.3.6 典型错误

[root@localhost logs]# /usr/local/nginx/sbin/nginx -c 
/usr/local/nginx/conf/nginx.conf
[root@localhost /]# nginx: [emerg] open() "/var/run/nginx/nginx.pid" failed (2: 
No such file or directory)
vim /usr/local/nginx/conf/nginx.conf
pid       /usr/local/nginx/logs/nginx.pid;

标签:文件,conf,FastDFS,storage,nginx,fastdfs,分布式文件系统,fdfs
来源: https://www.cnblogs.com/china-soldier/p/15847877.html