对于FastDFS你必须知道的事(最全,精美版)

2021-01-26 15:34:10 浏览数 (1)

1FastDFS简介

为什么使用它?

1. 在分布式集群环境下,文件上传至节点A,这时通过负载均衡算法,访问到节点B,则不能访问到文件,这时会出现有时能访问有时不能访问的问题 2. 同时要考虑为文件做冗余备份、负载均衡、线性扩容等功能,这些都是单节点文件上传所不具备的

FastDFS体系结构

  • FastDFS是一个开源的轻量级分布式文件系统(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
  • FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
  • FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过Tracker server 调度最终由 Storage server 完成文件上传和下载。
  • Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到Storage server提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将storage称为存储服务器。

上传流程

客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息

包括:组名,虚拟磁盘路径,数据两级目录,文件名。

group1/M00/00/00/rBcRCl_bcZaAFW_dAABKuOa99Po198.png

  1. 组名:文件上传后所在的 storage 组名称,在文件上传成功后有storage 服务器返回,需要客户端自行保存。
  2. 虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。
  3. 数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
  4. 文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

2FastDFS安装

我们使用Docker安装FastDFS

拉取镜像

docker pull morunchang/fastdfs

运行tracker

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

运行storage

docker run -d --name storage --net=host -e TRACKER_IP=<your tracker server address>:22122 -e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh

上面是示例,下面是实例,记得换你的公网ip (比如我的是 39.97.248.11)

docker run -d --name storage --net=host -e TRACKER_IP=39.97.248.11:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh

使用的网络模式是–net=host,host模式可以不用映射容器端口宿主机, 替换为你机器的Ip即可 是组名,即storage的组 如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名

修改nginx的配置

进入storage的容器内部,修改nginx.conf

docker exec -it storage /bin/bash

进入后

vi /etc/nginx/conf/nginx.conf

添加以下内容(它默认已经存在,不用改)

location ~ /M00 { root /data/fast_data/data; ngx_fastdfs_module; }

禁止缓存:(这个一定要加,加在 ngx_fastdfs_module;下面哈)

add_header Cache-Control no-store;

(5)退出容器

exit

(6)重启storage容器

docker restart storage

查看tracker.conf和storage.conf配置文件

docker exec -it storage /bin/bash cd /etc/fdfs vim tracker.conf vim storage.conf


3搭建项目

创建文件上传微服务upload-service,通过fastdfs-client组件实现文件上传和删除的功能

(1)在spring cloud项目中创建子工程,修改pom.xml,引入依赖

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>

        <artifactId>zx-springcloud</artifactId>

        <groupId>com.zx</groupId>

        <version>1.0-SNAPSHOT</version>

    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>upload-service</artifactId>

    <dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

        </dependency>   

        <!-- FastDFS依赖 -->

        <dependency>

            <groupId>com.github.tobato</groupId>

            <artifactId>fastdfs-client</artifactId>

            <version>1.26.7</version>

        </dependency>

    </dependencies>

</project>

(2)application.yml

代码语言:javascript复制
server:

  port: 9004

spring:

  application:

    name: upload-service

  servlet:

    multipart:

      enabled: true

      max-file-size: 10MB #单个文件上传大小

      max-request-size: 20MB #总文件上传大小

fdfs:

  # 链接超时

  connect-timeout: 60

  # 读取时间

  so-timeout: 60

  # 生成缩略图参数

  thumb-image:

    width: 150

    height: 150

  tracker-list: 39.97.248.11:22122  #你的公网ip

eureka:

  client:

    service-url:

      defaultZone: http://127.0.0.1:10086/eureka

  instance:

    #更倾向于使用ip地址,而不是主机名

    prefer-ip-address: true

    #ip地址

    ip-address: 127.0.0.1

    #续约间隔,默认30秒

    lease-renewal-interval-in-seconds: 5

    #服务的实效时间, 默认90秒

    lease-expiration-duration-in-seconds: 5

(3)启动类UploadApplication

代码语言:javascript复制
package com.zx;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication

@EnableDiscoveryClient

public class UploadApplication {

    public static void main(String[] args) {



     SpringApplication.run(UploadApplication.class, args);

    }

}

(4) FastDfs配置类DfsConfig

代码语言:javascript复制
package com.zx.upload.config;

import com.github.tobato.fastdfs.FdfsClientConfig;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.EnableMBeanExport;

import org.springframework.context.annotation.Import;

import org.springframework.jmx.support.RegistrationPolicy;

@Configuration

@Import(FdfsClientConfig.class)

public class DfsConfig {

}

工具类FileDfsUtil

调用fastdfs-client工具方法实现文件上传和删除

代码语言:javascript复制
package com.zx.upload.config;

import com.github.tobato.fastdfs.domain.fdfs.StorePath;

import com.github.tobato.fastdfs.service.FastFileStorageClient;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import org.springframework.util.StringUtils;

import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

@Component

public class FileDfsUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class);

    @Resource

    private FastFileStorageClient storageClient ;

    /**

     * 上传文件

     */

    public String upload(MultipartFile multipartFile) throws Exception{

        String originalFilename = multipartFile.getOriginalFilename().

                                  substring(multipartFile.getOriginalFilename().

                                  lastIndexOf(".")   1);

 


        StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(

                              multipartFile.getInputStream(),

                              multipartFile.getSize(),originalFilename , null);

        return storePath.getFullPath() ;

    }

    /**

     * 删除文件

     */

    public void deleteFile(String fileUrl) {

        if (StringUtils.isEmpty(fileUrl)) {

            LOGGER.info("fileUrl == >>文件路径为空...");

            return;

        }

        try {

            StorePath storePath = StorePath.parseFromUrl(fileUrl);

            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());

        } catch (Exception e) {

            LOGGER.info(e.getMessage());

        }

    }

}

FileController

创建文件上传和删除功能的controller,实现文件删除

代码语言:javascript复制
package com.zx.controller;

import com.zx.config.FileDfsUtil;
import io.swagger.annotations.Api;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * @Author CaesarChang张旭
 * @Date 2020/12/17  9:15 上午
 * @Version 1.0
 */
@RestController
@Api(tags={"文件管理类"})
public class FileController {


    @Autowired
    private FileDfsUtil fileDfsUtil;


    /**
     * 上传文件
     * @param file
     * @return
     */
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
    public ResponseEntity<String> uploadFile(@RequestParam(value = "file") MultipartFile file) {

        String result = null;
        try {
            String path = fileDfsUtil.upload(file);
            if (StringUtils.isEmpty(path)) {
                result = "上传失败";
                return new ResponseEntity<>(result, HttpStatus.resolve(400));
            } else {
                result=path;
                return new ResponseEntity<>(result, HttpStatus.resolve(200));
            }

        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>("服务器异常", HttpStatus.resolve(400));
        }


    }


    /**
     * 删除文件
     * @param filePathName
     * @return
     */
    @RequestMapping(value = "/deleteByPath",method = RequestMethod.GET)
    public ResponseEntity<String> deleteByPath(String filePathName) {

        fileDfsUtil.deleteFile(filePathName);
        return new ResponseEntity<>("删除成功", HttpStatus.resolve(200));
    }







}

postman测试

上传测试


删除测试

拜了个拜!么么哒

0 人点赞