快速构建FastDFS分布式文件系统,该篇文章你不得不看哦

前言

说起分布式文件管理系统,大家可能很容易想到 HDFS、GFS 等系统,前者是 Hadoop 的一部分,后者则是 Google 提供的分布式文件管理系统。除了这些之外,国内淘宝和腾讯也有自己的分布式文件管理系统,都叫 TFS(Taobao File System 和 Tencent File System)。

相对于上面提到的这些分布式文件管理系统而言,FastDFS 可能离我们 Java 工程师更近一些,因为文件上传这个功能太常见了,而想要搭建独立的分布式文件管理系统,FastDFS+Nginx 组合无疑是最佳方案。因此,松哥今天就来和大家简单聊一聊这个问题。

什么是FastDFS

1.1 FastDFS 简介

FastDFS 由淘宝的余庆大佬在 2008 年开源的一款轻量级分布式文件管理系统,FastDFS 用 C 语言实现,支持 Linux、FreeBSD、MacOS 等类 UNIX 系统。FastDFS 类似 google FS,属于应用级文件系统,不是通用的文件系统,只能通过专有 API 访问,目前提供了 C 和 Java SDK ,以及 PHP 扩展 SDK。

这款开源软件从发布至今,历经数十年,这款开源软件的生命力依然旺盛,在业界依然备受推崇,当然这也得益于作者一直在不断完善该软件。

FastDFS 专为互联网应用量身定做,解决大容量文件存储问题,追求高性能和高扩展性,它可以看做是基于文件的 key/value 存储系统,key 为文件 ID,value 为文件内容,因此称作分布式文件存储服务更为合适。

1.2 为什么需要 FastDFS

传统的企业级开发对于高并发要求不是很高,而且数据量可能也不大,在这样的环境下文件管理可能非常 Easy。

但是互联网应用访问量大、数据量大,在互联网应用中,我们必须考虑解决文件大容量存储和高性能访问的问题,而 FastDFS 就特别适合干这件事情,常见的图片存储、视频存储、文档存储等等我们都可以采用 FastDFS 来做。

1.3 FastDFS 架构

作为一款分布式文件管理系统,FastDFS 主要包括四个方面的功能:

文件存储
文件同步
文件上传
文件下载

这个方面的功能,基本上就能搞定我们常见的文件管理需求了。

下面这是一张来自 FastDFS 官网的系统架构图:

快速构建FastDFS分布式文件系统,该篇文章你不得不看哦_第1张图片

从上面这张图中我们可以看到,FastDFS 架构包括 Tracker 和 Storage 两部分,看名字大概就能知道,Tracker 用来追踪文件,相当于是文件的一个索引,而 Storage 则用来保存文件。

我们上传文件的文件最终保存在 Storage 上,文件的元数据信息保存在 Tracker 上,通过 Tracker 可以实现对 Storage 的负载均衡。

Storage 一般会搭建成集群,一个 Storage Cluster 可以由多个组构成,不同的组之间不进行通信,一个组又相当于一个小的集群,组由多个 Storage Server 组成,组内的 Storage Server 会通过连接进行文件同步来保证高可用。

java客户端调用

关于FastDFS、Nginx及依赖环境的安装就不再讲解了,大家可以参考官网和度娘都很容易找到资料

我们就用 Java 客户端来测试一下文件上传下载。

首先我们来创建一个普通的 Maven 工程,添加如下依赖:

<dependency>
    <groupId>net.oschina.zcx7878</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.27.0.0</version>
</dependency>

然后,在项目的 resources 目录下添加 FastDFS 的配置文件 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 = 192.168.91.128:22122
fastdfs.connection_pool.enabled = true
fastdfs.connection_pool.max_count_per_entry = 500
fastdfs.connection_pool.max_idle_time = 3600
fastdfs.connection_pool.max_wait_time_in_ms = 1000

这里的配置基本上都能见名知义,我就不挨个解释了。这里先配置下 fastdfs.tracker_servers,这是 Tracker 的地址,根据实际情况配置即可。

fastdfs.http_secret_key 配置这里先不用管它,后面我会跟大家解释。

- 文件上传
配置完成后,先来看文件上传,代码如下:

@Test
void testUpload() {
    try {
        ClientGlobal.initByProperties("fastdfs-client.properties");
        TrackerClient tracker = new TrackerClient();
        TrackerServer trackerServer = tracker.getConnection();
        StorageServer storageServer = null;
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        NameValuePair nvp[] = null;
        //上传到文件系统
        String fileId = client.upload_file1("C:\\Users\\javaboy\\Pictures\\picpick\\1.png", "png",
                nvp);
        logger.info(fileId);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这里,首先加载配置文件,然后构造一个 TrackerClient 对象,接着再根据这个对象获取到一个 TrackerServer,然后创建一个 StorageClient1 实例。NameValuePair 中保存的是文件的元数据信息,如果有的话,就以 key/value 的方式来设置,如果没有的话,直接给一个 null 即可。

最后,调用 client 的 upload_file1 方法上传文件,第一个参数是文件路径,第二个参数是文件的扩展名,第三个参数就是文件的元数据信息,这个方法的返回值,就是上传文件的访问路径。执行该方法,打印日志如下:

2020-02-29 17:46:03.017  INFO 6184 --- [           main] o.j.fastdfs.FastdfsApplicationTests      : group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png

group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就是文件的路径,此时,在浏览器中输入 http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就可以看到上传的图片了。

- 文件下载

@Test
void testDownload() {
    try {
        ClientGlobal.initByProperties("fastdfs-client.properties");
        TrackerClient tracker = new TrackerClient();
        TrackerServer trackerServer = tracker.getConnection();
        StorageServer storageServer = null;
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);
        byte[] bytes = client.download_file1("group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png");
        FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\javaboy\\Pictures\\picpick\\666.png"));
        fos.write(bytes);
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这段代码就很好理解了,直接调用 download_file1 方法获取到一个 byte 数组,然后通过 IO 流写出到本地文件即可。

- 安全问题
现在,任何人都可以访问我们服务器上传文件,这肯定是不行的,这个问题好解决,加一个上传时候的令牌即可。

首先我们在服务端开启令牌校验:

vi /etc/fdfs/http.conf
快速构建FastDFS分布式文件系统,该篇文章你不得不看哦_第2张图片配置完成后,记得重启服务端:

./nginx -s stop
./nginx

接下来,在前端准备一个获取令牌的方法,如下:

@Test
public void getToken() throws Exception {
    int ts = (int) Instant.now().getEpochSecond();
    String token = ProtoCommon.getToken("M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png", ts, "FastDFS1234567890");
    StringBuilder sb = new StringBuilder();
    sb.append("?token=").append(token);
    sb.append("&ts=").append(ts);
    System.out.println(sb.toString());
}

这里,我们主要是根据 ProtoCommon.getToken 方法来获取令牌,注意这个方法的第一个参数是你要访问的文件 id,**注意,这个地址里边不包含 group,千万别搞错了;**第二个参数是时间戳,第三个参数是密钥,密钥要和服务端的配置一致。

将生成的字符串拼接,追加到访问路径后面,如:http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png?token=7e329cc50307000283a3ad3592bb6d32&ts=1582975854。「此时访问路径里边如果没有令牌,会访问失败。」

写在最后

怎么样,搭建FastDFS是不是非常Easy呢,更详情的请点击链接 包括了其中安装的步骤

想了解更多的知识,请关注我吧 _

你可能感兴趣的:(快速构建FastDFS分布式文件系统,该篇文章你不得不看哦)