FastDFS的学习

Updated on with 0 views and 0 comments

FastDFS的学习

FastDFS

FastDFS体系结构

FastDFS是用 c 语言编写的一款开源的分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。

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称为存储服务器。

image-20210224101539891

上传流程

image-20210224101859667

客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

image-20210224101924665

组名:文件上传后所在的 storage 组名称,在文件上传成功后有storage 服务器返回,需要客户端自行保存。

虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项store_path*对应。如果配置了

store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。

数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据

文件。

文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储

服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

文件下载流程

img

FastDFS搭建

安装FastDFS镜像

我们使用Docker搭建FastDFS的开发环境

启动docker容器

systemctl start docker

使用如下命令回复镜像

docker load -i fastdfs.tar 

没有fastdfs镜像,通过命令拉取镜像(已经下载了该镜像,大家无需下载了)

docker pull morunchang/fastdfs

查看网卡

docker network ls

创建网卡命令

docker network create mynet

构建网络成功后,所有加入到该用户自定义网络的容器即可通过容器名称相互连接。

运行tracker 使用自带的host网卡

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

运行storage

docker run -id --name storage --net=host -e TRACKER_IP=192.168.153.130:22122 -e GROUP_NAME=group1 morunchang/fastdfs sh storage.sh
  • 使用的网络模式是–net=host, 192.168.188.128是宿主机的IP
  • group1是组名,即storage的组
  • 如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名

配置Nginx

Nginx在这里主要提供对FastDFS图片访问的支持,FastDFS容器中已经集成了Nginx,我们需要修改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;
}

禁止缓存:

add_header Cache-Control no-store;

img

退出容器

exit

重启storage容器

docker restart storage

文件上传Demo

创建文件管理微服务dongyimai-file-service,该工程主要用于实现文件上传以及文件删除等功能。

依赖

<dependencies>
    <dependency>
        <groupId>cn.bestwu</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27</version>
    </dependency>
    <dependency>
        <groupId>com.bh</groupId>
        <artifactId>dongyimai-common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

配置

在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf

#tracker服务器IP地址和端口号
tracker_server=192.168.188.128:22122

tracker_server: tracker服务器IP和端口设置

注意:项目不要放在中文路径下,否在加载fdfs_client.conf找不到路径。

创建测试类TestFastDFS

public class TestFastDFS {
    public static void main(String[] args) throws IOException, MyException {
        // 1、加载配置文件,配置文件中的内容就是 tracker 服务的地址。
        //注意:路径中不要有中文
        ClientGlobal.init("D:\\bh linfo\\IdeaProjects\\fourth\\day09\\dongyimai-parent\\dongyimai-service\\dongyimai-file-service\\src\\main\\resources\\fdfs_client.conf");
        // 2、创建一个 TrackerClient 对象。直接 new 一个。
        TrackerClient trackerClient = new TrackerClient();
        // 3、使用 TrackerClient 对象创建连接,获得一个 TrackerServer 对象。
        TrackerServer trackerServer = trackerClient.getConnection();
        // 4、创建一个 StorageServer 的引用,值为 null,由 TrackerServer 分配
        StorageServer storageServer = null;
        // 5、创建一个 StorageClient 对象,需要两个参数 TrackerServer 对象、StorageServer 的引用
        StorageClient storageClient = new StorageClient(trackerServer, storageServer);
        // 6、使用 StorageClient 对象上传图片。
        //扩展名不带“.”
        String[] strings = storageClient.upload_file("C:/Users/Administrator/Desktop/upload/mimiup.png", "png",
                null);
        // 7、返回数组。包含组名和图片的路径。
        for (String string : strings) {
            System.out.println(string);
        }
    }
}

注意:如果出现连接图片服务器超时失败的情况

请检查图片linux服务器是否启动、是否开启了端口22122、23000以及8080的防火墙端口,如果未开启需要开启。

firewall-cmd --add-port=22122/tcp --permanent
firewall-cmd --add-port=23000/tcp --permanent
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload

控制台输出如下结果:

image-20210907233527554

在浏览器输入:

http://192.168.153.130:8080/group1/M00/00/00/wKiZgmE3hiiAZw3mAAL-Jt8ah20407.png

即可看到所上传的图片。

文件上传Web端

主启动类 com.bh

@SpringBootApplication
public class FastDFSApp {
    public static void main(String[] args) {
        SpringApplication.run(FastDFSApp.class);
    }
}

配置

spring:
  application:
    name: fastDFS
  servlet:
    multipart:
      max-file-size: 10MB

server:
  port: 8001

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

feign:
  hystrix:
    enabled: true

file:
  url: http://192.168.153.130:8080/

工具类 com.bh.utils

public class FastDFSClient {

	private TrackerClient trackerClient = null;
	private TrackerServer trackerServer = null;
	private StorageServer storageServer = null;
	private StorageClient1 storageClient = null;

	public FastDFSClient(String conf) throws Exception {
		if (conf.contains("classpath:")) {
			conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
		}
		ClientGlobal.init(conf);
		trackerClient = new TrackerClient();
		trackerServer = trackerClient.getConnection();
		storageServer = null;
		storageClient = new StorageClient1(trackerServer, storageServer);
	}

	/**
	 * 上传文件方法
	 * <p>Title: uploadFile</p>
	 * <p>Description: </p>
	 * @param fileName 文件全路径
	 * @param extName 文件扩展名,不包含(.)
	 * @param metas 文件扩展信息
	 * @return
	 * @throws Exception
	 */
	public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
		String result = storageClient.upload_file1(fileName, extName, metas);
		return result;
	}

	public String uploadFile(String fileName) throws Exception {
		return uploadFile(fileName, null, null);
	}

	public String uploadFile(String fileName, String extName) throws Exception {
		return uploadFile(fileName, extName, null);
	}

	/**
	 * 上传文件方法
	 * <p>Title: uploadFile</p>
	 * <p>Description: </p>
	 * @param fileContent 文件的内容,字节数组
	 * @param extName 文件扩展名
	 * @param metas 文件扩展信息
	 * @return
	 * @throws Exception
	 */
	public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {

		String result = storageClient.upload_file1(fileContent, extName, metas);
		return result;
	}

	public String uploadFile(byte[] fileContent) throws Exception {
		return uploadFile(fileContent, null, null);
	}

	public String uploadFile(byte[] fileContent, String extName) throws Exception {
		return uploadFile(fileContent, extName, null);
	}
}

控制层 com.bh.controller 中创建 UploadController.java

@RestController
public class UploadController {

    @Value("${file.url}")
    private String FILE_SERVER_URL;//文件服务器地址

    @PostMapping("/upload")
    public Result upload(@RequestParam(name = "file") MultipartFile file) {
        //1、取文件的扩展名
        String originalFilename = file.getOriginalFilename();
        String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        try {
            //2、创建一个 FastDFS 的客户端
            //3、注意项目不要在中文路径下,否则加载不到这个配置文件。
            FastDFSClient fastDFSClient = new FastDFSClient("classpath:fdfs_client.conf");
            //3、执行上传处理
            String path = fastDFSClient.uploadFile(file.getBytes(), extName);
            //4、拼接返回的 url 和 ip 地址,拼装成完整的 url
            String url = FILE_SERVER_URL + path;
            return new Result(true, StatusCode.OK, url);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, StatusCode.ERROR, "上传失败");
        }
    }

}

标题:FastDFS的学习
作者:HB2Ocean
地址:http://future-hb.top:8080/articles/2021/09/12/1631456376246.html