Java高级架构之FastDFS分布式文件集群详解

网友投稿 382 2023-01-08


Java高级架构之FastDFS分布式文件集群详解

FastDFS简介

FastDFS是一款开源的轻量级分布式文件系统,使用C实现,支持linux、BSD等unix-like操作系统。值得注意的是,fastdfs并不是通用的文件系统,只能通过专用的API访问。

fastdfs为互联网应用量身定做,解决了大容量文件存储的问题,fastdfs追求高性能和高扩展性。fastdfs的主要概念:

tracker-server:跟踪服务器。用于跟踪文件,主要起调度作用。在内存中记录了所有存储组和存储服务器的状态信息,是客户端和数据存储的主要枢纽。相比GFS更为精简,因为不记录文件索引。

storage-server: 存储服务器。用于存储文件。直接使用操作系统的文件系统来管理和组织文件。

group: 组,卷。多个服务器存在一个组中,在一个组中的服务器存储的文件是完全相同的,并且同一个组的服务器地位是对等的。对于文件的操作可以在任意一个组中的服务器上进行。

metadata: 元数据。以键值对的方式存储,用于存储文件的相关信息。

各大存储系统的对比

话说没有对比就没有伤害,fastdfs也不是万能的,需要根据业务来选择适合的存储系统。

存储系统

适合存储的文件类型

文件分布情况

系统性能

复杂度

FUSE(用户文件系统)

POSIX()

备份机制

通讯协议接口

社区情况

实现语言

FastDFS

4KB至500MB

将小文件合并存储

很高

简单

不支持

不支持

组内冗余备份

HTTP API

国内用户

C

TFS

所有文件

小文件合并以块组织分片

-

复杂

不支持

不支持

块存储多份,主辅灾备

HTTP API

C++

MFS

大于64K

分片存储

Master节点占用内存较高

-

支持

支持

多点备份,动态冗余

使用FUSE挂载

较多

Perl

HDFS

大文件

大文件分片块存储

-

简单

支持

支持

多副本

原生API

较多

java

Ceph

对象大文件

OSD一主多从

-

复杂

支持

支持

多副本

原生API

较少

C++

MogileFS

海量小图片

-

复杂

支持

不支持

动态冗余

原生API

文档少

Perl

ClusterFS

大文件

-

-

简单

支持

支持

-

-

C

github项目主页: https://github.com/happyfish100/fastdfs

FastDFS客户端与服务器端交互原理

FastDFS+Nginx整合

架构图

安装FastDFS

mkdir /source

cd /source

yum install -y gcc gcc-c++ make cmake wget libevent

wget https://github.com/happyfish100/libfastcommon/archive/V1.0.35.tar.gz

wget https://github.com/happyfish100/fastdfs/archive/V5.10.tar.gz

tar -zxvf V1.0.35.tar.gz

tar -zxvf V5.10.tar.gz

cd libfastcommon-1.0.35

./make.sh

./make.sh install

ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so

cd ../

cd fastdfs-5.10/

./make.sh

./make.sh install

cd ../

rm -rf libfastcommon-1.0.35

rm -rf fastdfs-5.10

cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf

cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf

cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf

mkdir -p /data/fdfs/tracker

mkdir -p /data/fdfs/storage

ln -s /usr/bin/stop.sh /usr/local/bin/stop.sh

ln -s /usr/bin/restart.sh /usr/local/bin/restart.sh

修改配置文件

修改跟踪器配置文件:

base_path=/data/fdfs/tracker

修改存储器配置文件:

base_path=/data/fdfs/storage

store_path0=/data/fdfs/storage

tracker_server=192.168.80.3:22122

修改客户端配置文件:

base_path=/data/fdfs/client

tracker_server=192.168.80.3:22122

启动

/etc/init.d/fdfs_trackerd start

/etc/init.d/fdfs_storaged start

netstat -tunlap | grep :22122

tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 7247/fdfs_trackerd

tcp 0 0 192.168.80.3:22122 192.168.80.3:39318 ESTABLISHED 7247/fdfs_trackerd

tcp 0 0 192.168.80.3:39318 192.168.80.3:22122 ESTABLISHED 7444/fdfs_storaged

启动后要查看状态, 出现 active (exited) 字样可以尝试重启服务。

测试

/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /source/FastDFS_v5.05.tar.gz

group1/M00/00/00/wKhQA1ysjsGAPjXbAAVFOL7FJU4.tar.gz

文件存储在:

ll /data/fdfs/storage/data/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz

安装Nginx并配置模块

# 安装Nginx需要的pcre(Perl兼容正则表达式)库,允许Nginx使用rewrite模块提供URL重写功能。

yum install pcre pcre-devel perl-ExtUtils-Embed -y

# 安装openssl-devel,允许Nginx提供HTTPS服务。

yum install openssl-devel -y

# 下载软件包

cd /source

wget http://59.80.44.46/nginx.org/download/nginx-1.14.2.tar.gz

wget http://nchc.dl.sourceforge.net/project/fastdfs/FastDFS%20Nginx%20Module%20Source%20Code/fastdfs-nginx-module_v1.16.tar.gz

# 解压软件包

tar xvf nginx-1.14.2.tar.gz

tar xvf fastdfs-nginx-module_v1.16.tar.gz

# 创建必要的软连接

ln -s /usr/include/fastdfs/ /usr/local/include/fastdfs

ln -s /usr/include/fastcommon/ /usr/local/include/fastcommon

cp FastDFS/conf/http.conf /etc/fdfs/

cp FastDFS/conf/mime.types /etc/fdfs/

cp fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/

mkdir -p /data/fdfs/fastdfs-nginx-module

修改配置文件 /etc/fdfs/mod_fastdfs.conf :

connect_timeout=10

base_path=/data/fdfs/fastdfs-nginx-module

# 配置服务器的地址

tracker_server=192.168.80.3:22122

url_have_group_name = true

store_path0=/data/fdfs/storage

mkdir /applications

mkdir /tmp/nginx

useradd nginx -s /sbin/nologin -M

cd nginx-1.14.2

./configure \

--user=nginx \

--group=nginx \

--prefix=/applications/nginx-1.14.2 \

--with-http_ssl_module \

--with-http_gzip_static_module \

--http-client-body-temp-path=/tmp/nginx/client \

--http-proxy-temp-path=/tmp/nginx/proxy \

--http-fastcgi-temp-path=/tmp/nginx/cgi \

--with-poll_module \

--with-file-aio \

--with-http_realip_module \

--with-http_addition_module \

--with-http_random_index_module \

--with-pcre \

--with-http_stub_status_module \

--with-stream \

--add-module=/source/fastdfs-nginx-module/src

make

make install

ln -s /applications/nginx-1.14.2/ /applications/nginx

chown -R nginx.nginx /applications/nginx

chown -R nginx.nginx /applications/nginx-1.14.2/

chown -R nginx.nginx /tmp/nginx/

修改配置文件 /applications/nginx/conf/nginx.conf , 在http区块添加:

server {

listen 8000;

server_name media;

location / {

root html;

index index.html index.htm;

}

# 拦截文件请求,转发到下面的模块

location ~/group[0-9] {

ngx_fastdfs_module;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

测试配置文件正确性并启动:

/applications/nginx/sbin/nginx -t

/applications/nginx/sbin/nginx

删除临时文件:

rm -rf FastDFS

rm -rf fastdfs-nginx-module

rm -rf libfastcommon-1.0.35

rm -rf nginx-1.14.2

测试Nginx文件下载功能, 在浏览器输入: http://192.168.80.3:8000/group1/M00/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz

一个nginx只能访问一个storage服务器的数据,所以多个storage服务器要配置多个nginx,然后将nginx按照请求路径中的组id(groupid)进行路由。

简单的启动停止服务的脚本:

# start-service

# usage: ./start-service

echo "============================================Sync datetime==========================================="

ntpdate time7.aliyun.com

echo "===========================================Getting status==========================================="

/etc/init.d/fdfs_trackerd status

/etc/init.d/fdfs_storaged status

echo "==========================================Starting service=========================================="

/etc/init.d/fdfs_storaged start

/etc/init.d/fdfs_trackerd start

echo "===========================================Getting status==========================================="

/etc/init.d/fdfs_trackerd status

/etc/init.d/fdfs_storaged status

echo "=========================================Testing config file========================================"

/applications/nginx/sbin/nginx -t

echo "=========================================Starting web server========================================"

/applications/nginx/sbin/nginx

echo "=======================================Getting network status======================================="

sleep 5s

netstat -tunlap | grep :22122

netstat -tunlap | grep :8000

# stop-service

# usage: ./stop-service

echo "===========================================Getting status==========================================="

/etc/init.d/fdfs_trackerd status

/etc/init.d/fdfs_storaged status

echo "==========================================Stopping service=========================================="

/etc/init.d/fdfs_storaged stop

/etc/init.d/fdfs_trackerd stop

echo "========================================Stopping web server========================================="

kill `cat /applications/nginx/logs/nginx.pid`

echo "===========================================Getting status==========================================="

/etc/init.d/fdfs_trackerd status

/etc/init.d/fdfs_storaged status

echo "=======================================Getting network status======================================="

sleep 5s

netstat -tunlap | grep :22122

netstat -tunlap | grep :8000

基于Token的防盗链实现

FastDFS内置使用Token的方式实现防盗链,Token是带有时效性的,Token中包含了文件id、时间戳ts和token。在FastDFS中使用URL带上ts和token的方式请求资源。在FastDFS中提供了生成Token的算法,扩展模块会对Token进行验证。由于Token的生成和校验都在服务器端,因此不会存在安全性问题。链接示例:

http://192.168.1.15:8080/group1/M01/01/01/wKgBD01c15nvKU1cAABAOeCdFS466570.c?token=b32cd06a53dea4376e43d71cc882f9cb&ts=1297930137

在 /etc/fdfs/http.conf 中修改:

# 开启Token校验

http.anti_steal.check_token=true

# Token的声明周期为240秒

http.anti_steal.token_ttl=240

# 加密字符串,可以使用 openssl rand -base64 64 生成

http.anti_steal.secret_key=2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw

# Token校验失败的时候返回的图片

http.anti_steal.token_check_fail=/data/fdfs/error.svg

使用Java客户端验证:

将客户端安装到本地仓库:

git clone https://github.com/happyfirJLBZgNsh100/fastdfs-client-java.git

cd fastdfs-client-java

mvn clean install

使用Maven创建一个普通的项目,在POM文件中添加依赖:

org.csource

fastdfs-client-java

1.27-SNAPSHOT

在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 = true

fastdfs.http_secret_key = 2scPwMPctXhbLVOYB0jyuyQzytOofmFCBIYe65n56PPYVWrntxzLIDbPdvDDLJM8QHhKxSGWTcr+9VdG3yptkw

fastdfs.http_tracker_http_port = 8080

fastdfs.tracker_servers = 192.168.80.3:22122

创建 com.bluemiaomiao.Demo.java 类文件:

package com.bluemiaomiao;

import org.csource.common.MyException;

import org.csource.fastdfs.ClientGlobal;

import org.csource.fastdfs.ProtoCommon;

import java.io.IOException;

import java.security.NoSuchAlgorithmException;

import java.util.Properties;

public class Demo {

public static void main(String[] args) throws IOException, MyException, NoSuchAlgorithmException {

// 加载配置文件

Properties prop = new Properties();

prop.load(Demo.class.getResourceAsStream("/fastdfs-client.properties"));

ClientGlobal.initByProperties(prop);

// 显示初始化配置信息

System.out.println(ClientGlobal.configInfo());

// 使用文件上传工具返回的地址,一般情况下保存在数据库中

String remoteFileName = "group1/M00/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz";

// 获取当前时间戳

int ts = (int)(System.currentTimeMillis()/1000);

// 获取Token, 传入的文件ID不要含有分组信息

String token = ProtoCommon.getToken("M00/00/00/wKhQA1ysjSGAPjXbAAVFOL7FJU4.tar.gz", ts, prop.getProperty("fastdfs.http_secret_key"));

// 使用浏览器访问返回的URL

System.out.println("http://192.168.80.3:8000/" + remoteFileName + "?token=" + token + "&ts=" + ts);

}

}

如果访问时显示防盗链图片,可能是测试客户端与服务器之间的之间有一定差距,两个主机之间不能有分钟级别的差距,可以使用如下方法同步服务器:

# 安装同步时间服务器的客户端, Windows系统也需要与该服务器同步

# 控制面板->时钟和区域->设置日期和时间->Internet时间->更改设置

yum install ntpdate

ntpdate time7.aliyun.com

整合FastDHT实现数据去重

FastDHT是分布式哈希系统(DHT),使用BerkeleyDB做数据存储,使用libevent做网络IO处理。依赖于libfastcommon组件。

下载

去Oracle官方网站下载 Berkeley DB 数据库,去Fastdfs的GitHub主页下载FastDHT的源码包。由于之前已经安装过linevent和libfastcommon,因此只需要安装数据库和FastDHT即可。

安装配置数据库与FastDHT

tar -xvf db-6.2.23.tar.gz

cd db-6.2.23/build_unix/

../dist/configure --prefix=/applications/db-6.2.23

cd ../../

rm -rf db-6.2.23

unzip fastdht-master.zip

cd fastdht-master

vim make.sh

修改第27行代码:

CFLAGS='-Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -I /applications/db-6.2.23/include/ -L /applications/db-6.2.23/lib/'

-I : 指定数据库提供的头文件目录

-L : 指定数据库提供的库文件目录

./make.sh

./make.sh install

cd ../

rm -rf fastdht-master

配置

mkdir /data/fdht

修改 /etc/fdht/fdht_client.conf 内容:

base_path=/data/fdht

#include /etc/fdht/fdht_servers.conf

修改 /etc/fdht/fdht_servers.conf 内容:

group0 = 192.168.80.3:11411

修改 /etc/fdht/fdhtd.conf 内容:

base_path=/data/fdht

#include /etc/fdht/fdht_servers.conf

修改 /etc/fdfs/storage.conf 内容:

check_file_duplicate=1

key_namespace=FastDFS

keep_alive=1

#include /etc/fdht/fdht_servers.conf

主要需要包含服务器端配置文件。

ln -s /applications/db-6.2.23/lib/libdb-6.2.so /usr/lib/libdb-6.2.so

ln -s /applications/db-6.2.23/lib/libdb-6.2.so /usr/lib64/libdb-6.2.so

启动并测试

fdhtd /etc/fdht/fdhtd.conf

重启使用:

fdhtd /etc/fdht/fdhtd.conf restart

查看结果:

netstat -tunlap | grep :11411

tcp 0 0 0.0.0.0:11411 0.0.0.0:* LISTEN 20605/fdhtd

由于安装Fasthttp://DHT的时候关闭了FastDFS,因此需要启动FastDFS

./start-service

修改之前的 start-service 脚本, 在启动tracker和storage服务之前添加:

fdhtd /etc/fdht/fdhtd.conf

在查看tracker和ngixn网络状态之前添加:

netstat -tunlap | grep :11411

测试:

fdfs_upload_file /etc/fdfs/client.conf /source/db-6.2.23.tar.gz

group1/M00/00/00/wKhQA1yu2L6APTk-AqQOLABfhaQ.tar.gz

fdfs_upload_file /etc/fdfs/client.conf /source/db-6.2.23.tar.gz

group1/M00/00/00/wKhQA1yu2MKAOmIiAqQOLHUWXfw.tar.gz

ll /data/fdfs/storage/data/00/00/

total 45268

-rw-r--r-- 1 root root 44305964 Apr 11 14:03 wKhQA1yu2L6AM0aiAqQOLKFBFuc.tar.gz

lrwxrwxrwx 1 root root 64 Apr 11 14:03 wKhQA1yu2L6APTk-AqQOLABfhaQ.tar.gz -> /data/fdfs/storage/data/00/00/wKhQA1yu2L6AM0aiAqQOLKFBFuc.tar.gz

lrwxrwxrwx 1 root root 64 Apr 11 14:03 wKhQA1yu2MKAOmIiAqQOLHUWXfw.tar.gz -> /data/fdfs/storage/data/00/00/wKhQA1yu2L6AM0aiAqQOLKFBFuc.tar.gz

自定义 fastdfs-spring-boot-starter

为了快速构建SpringBoot项目,我们可以自定义一个场景启动器来解决。详细信息: https://github.com/bluemiaomiao/fastdfs-spring-boot-starter .

下面使用SpringBoot构建一个示例项目:

添加依赖:

com.bluemiaomiao

fastdfs-spring-boot-starter

1.0-SNAPSHOT

在主配置类中添加注解:

@EnableFastdfsClient

@SpringBootApplication

public class DemoApplication {

@Autowired

private FastdfsClientService fastdfsClientService;

public static void main(String[] args) {

SpringApplication.run(DemoApplication.class, args);

}

}

此时将会自动初始化好全局客户端。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:微服务网关业务聚合(微服务网关zuul)
下一篇:详解Java异常处理最佳实践及陷阱防范
相关文章

 发表评论

暂时没有评论,来抢沙发吧~