搭建分布式文件系统FastDFS集群

FastDFS是为互联网应用量身定做的一套分布式文件存储系统,非常适合用来存储用户图片、视频、文档等文件。对于互联网应用,和其他分布式文件系统相比,优势非常明显。出于简洁考虑,FastDFS没有对文件做分块存储,因此不太适合分布式计算场景。


在生产环境中往往数据存储量比较大,因此会大部分会选择分布式存储来解决,主要解决以下几个问题

  • 海量数据存储
  • 数据高可用(冗余备份)
  • 较高读写性能和负载均衡
  • 支持多平台多语言
  • 高并发问题

常见分布式存储对比

搭建分布式文件系统FastDFS集群


FastDFS 相关组件及原理

FastDFS介绍

FastDFS是一个C语言实现的开源轻量级分布式文件系统,支持Linux、FreeBSD、AID等Linux系统,解决了大量数据存储和读写负载等问题,适合存储4KB~500MB之间的小文件,如图片网站,短视频网站,文档,APP下载站等,UC,京东,支付宝,迅雷,酷狗等都有使用,其中UC基于FastDFS向用户提供网盘,广告和应用下载的业务。FastDFS与MogileFS、HDFS、TFS等都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务

FastDFS架构

FastDFS服务有三个角色: 跟踪服务(tracker server)、存储服务(storage server)和客户端(client)

tracker server: 跟踪服务,主要做调度工作,起到均衡的作用;负责管理所有的storage server和group,每个storage在启动后会连接Tracker,告知自己所属group等信息,并保持周期性心跳,tracker根据storage心跳信息,建立group --> [storage server list]的映射表;tracker管理的元数据很少,会直接存放在内存;tracker上的元信息都是由storage汇报的信息生成的,本身不需要持久化任何数据,tracker之间是对等关系,因此扩展tracker访问非常容器,之间增加tracker访问即可,所有tracker都接受storage心跳信息,生成元数据信息来提供读写访问(与其他master-slave架构的优势是没有单点,tracker也不会成为瓶颈,最终数据是和一个可用的storage server进行传输)

storage server: 存储服务器,主要提供容量和备份访问;以group为单位,每个group内可以包含多个storage server,数据互为备份,存储容量空间以group内容量最小的storage为准;建议group内的storage server配置相同;以group为单位组织存储能够方便的进行引用隔离、负载均衡和副本数定制;

缺点: group的容量受单机存储容量的限制,同时group内机器坏掉,数据恢复只能依赖group内其他机器重新同步(硬盘替换,重新挂载重启fdfs_storaged即可)

group存储策略

  • round robin (轮训)
  • load balance (选择最大剩余空间的组上传文件)
  • specify group (指定group上传)

group中storage存储依赖本地文件系统,storage可配置多个数据存储目录,磁盘不做raid,直接分别挂在到多个目录,将这些目录配置为storage的数据目录即可

storage接受写请求时,会根据配置好的规则,选择其中一个存储目录来存储文件;为避免单个目录下文件过多,storage第一次启动,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中

搭建分布式文件系统FastDFS集群


FastDFS工作流程

上传

搭建分布式文件系统FastDFS集群

FastDFS提供基本的文件访问接口,如upload、download、append、delete等

选择tracker server

集群中tracker之间是对等关系,客户端在上传文件时可用任意选择一个tracker

选择存储group

当tracker接受到upload file的请求时,会为该文件分配一个可以存储的group,目前支持选择group的规则为

1.Round Robin (所有group轮训使用)

2.Specified group (指定某个确定的group)

3.Load balance (剩余存储空间较多的group优先)

选择storage server

当选定group后,tracker会在group内选择一个storage server给客户端,目前支持选择server的规则为

1.Round Robin (所有server轮训使用)默认规则

2.根据IP地质进行排序选择第一个服务器 (IP地址最小者)

3.根据优先级进行排序 (上传优先级由storage server来设置,参数为upload_priority)

选择storage path (磁盘或者挂载点)

当分配好storage server后,客户端将向storage发送写文件请求,storage会将文件分配一个数据存储目录,目前支持选择存储路径的规则为:

1.round robin (轮训)默认

2.load balance 选择使用剩余空间最大的存储路径

选择下载服务器

目前支持的规则为

1.轮训方式,可以下载当前文件的任一storage server

2.从源storage server下载

生成file_id

选择存储目录后,storage会生成一个file_id,采用Base64编码,包含字段包括: storage server ip、文件创建时间、文件大小、文件CRC32校验码和随机数;每个存储目录下有两个256*256个子目录,storage会按文件file_id进行两次hash,路由到其中一个子目录,然后将文件file_id为文件名存储在该子目录下,最后生成文件路径: group名称、虚拟磁盘路径、数据两级目录、file_id

group1 /M00/02/44/wkgDRe348wAAAAGKYJK42378.sh

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

虚拟磁盘路径: 存储服务器配置的虚拟路径,与磁盘选项store_path*参数对应

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


同步机制

1.新增tracker服务器数据同步

由于storage server上配置了所有的tracker server,storage server和tracker server之间的通信是由storage server主动发起的,storage server为每台tracker server 启动一个线程进行通信;在通信过程中,若发现tracker server返回的本组storage server列表比本机记录少,就会将该tracker server上没有的storage server同步给该tracker,这样的机制使得tracker之间是对等的关系,数据保持一致

2.组内新增storage数据同步

若新增storage server或者其状态发生变化,tracker server都会将storage server列表同步给该组内所有storage server;以新增storage server为例,新加入storage server会主动连接tracker server,tracker server发现有新的storage server加入,就会将该组内所有的storage server返回给新加入的storage server,并重新将该组的storage server列表返回给该组内的其他storage server

3.组内storage数据同步

组内storage server之间是对等的,文件上传,删除等操作可以在组内任意一台storage server上进行。文件同步只能在同组内的storage server之间进行,采用push方式,即源服务器同步到目标服务器

A. 只在同组内的storage server之间同步

B. 源数据才需要同步,备份数据不再同步

C. 特例: 新增storage server时,由其中一台将已有的所有数据(包括源数据和备份数据)同步到新增服务器

storage server 7种状态

通过命令fdfs_monitor /etc/fdfs/client.conf可以查看ip_addr选项显示storage server当前状态

INIT       初始化,尚未得到同步已有数据的源服务器
WAIT_SYNC  等待同步,已得到同步已有数据的源服务器
SYNCING    同步中
DELETE     已删除,该服务器从本组中摘除
OFFLINE    离线
ONLINE     在线,尚不能提供服务
ACTIVE     在线,可以提供服务

组内增加storage server A状态变化过程:

1.storage server A主动连接tracker server,此时tracker server将storage serverA状态设置为INIT

2.storage server A向tracker server询问追加同步的源服务器和追加同步截止时间点(当前时间),若组内只有storage server A或者上传文件数为0,则告诉新主机不需要同步数据,storage serverA状态为ONLINE;若组内没有active状态及其,就返回错误给新机器,新机器重新尝试;否则tracker将其状态设置为WAIT_SYNC

3.假如分配了storage server B为同步源服务器和截止时间点,那么storage serverB将会截止时间点之前的所有数据同步给storage server A,并请求tracker设置storage server A状态为SYNCING;到了截止时间后,storage server B向storage server A的同步将由追加同步切换为正常binlog增量同步,当获取不到更多binlog时,请求tracker将storage server A同步完所有数据,暂时没有数据要同步时,storage server B请求tracker server将storage server A的状态设置为ONLINE

4.storage server B向storage server A同步完所有数据,暂时没有数据要同步时,storage server B请求tracker server将 storage server A的状态设置为ONLINE

5.当storage server A向tracker server发起心跳时,tracker server将其状态更改为ACTIVE,之后就是增量同步(binlog)

搭建分布式文件系统FastDFS集群

注: 整个源同步班过程是源机器启动弄一个同步线程,将数据Push到新机器,最大达到一个磁盘的IO,不能并发;由于源同步截止条件是获取不到binlog,系统繁忙,不断有新数据写入的情况,将会导致一直无法完成源同步


下载

搭建分布式文件系统FastDFS集群

client发送下载请求给某个tracker,必须带上文件名信息,tracker从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用于读请求;由于group内的文件同步是异步进行,可能出现文件没有同步到其他storage server上或者延迟的问题,可以使用nginx_fastdfs_module模块解决

搭建分布式文件系统FastDFS集群

关于文件去重

由于FastDFS本身不能对重复上传的文件进行去重,而FastDHT可以做到去重。FastDHT是一个高性能的分布式哈希系统,它是基于键值对存储的,而且它需要依赖于Berkeley DB作为数据存储的媒介,同时需要依赖于libfastcommon

由于业务需要,目前不存在文件去重的时候,如果需要可以自己简单了解一下FastDHT

FastDFS-Nginx扩展模块源码分析


安装FastDFS集群

本次环境架构

搭建分布式文件系统FastDFS集群

针对tracker.conf && storage.conf && mod_fastdfs.conf有一篇单独的文章介绍相关参数。有兴趣的可以看一下,也可以直接看默认的配置文件,对每个参数都有介绍

 

FastDFS 配置文件详解

09

环境说明

#nginx这里可以部署2台,加上keepliveed作高可用,由于我这里机器不足,就使用单台nginx进行代理
nginx  192.168.31.100 nginx


tracker 节点
tracker 01:192.168.31.101  FastDFS,libfastcommon,nginx,ngx_cache_purge
tracker 02:192.168.31.102  FastDFS,libfastcommon,nginx,ngx_cache_purge
#其中tracker不提供存储


Storage 节点
[group1]
storage 01:192.168.31.103  FastDFS,libfastcommon,nginx,fastdfs-nginx-module
storage 02:192.168.31.104  FastDFS,libfastcommon,nginx,fastdfs-nginx-module

[group2]
storage 03:192.168.31.105  FastDFS,libfastcommon,nginx,fastdfs-nginx-module
storage 04:192.168.31.106  FastDFS,libfastcommon,nginx,fastdfs-nginx-module

1.所有的服务器都需要安装nginx,主要是用于访问和上传无关;

2.tracker安装nginx主要为了提供http反向代理、负载均衡以及缓存服务

3.每一台storage服务器部署Nginx及FastDFS扩展模块,主要用于对storage存储的文件提供http下载访问,仅当前storage节点找不到文件时会向源storage主机发送rediect或者proxy动作

所有节点安装

关闭防火墙,selinux

systemctl stop firewalld
systemctl disable firewalld
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
setenforce 0
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

设置yum源

yum install -y wget
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

yum clean all 
yum makecache

温馨提示:除了nginx节点(192.168.31.100),其他节点都需要执行安装fastdfs和nginx

安装依赖包 (可解决99%的依赖问题)

yum -y install gcc gcc-c++ make autoconf libtool-ltdl-devel gd-devel freetype-devel libxml2-devel libjpeg-devel libpng-devel openssh-clients openssl-devel curl-devel bison patch libmcrypt-devel libmhash-devel ncurses-devel binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel glibc glibc-common glibc-devel libgcj libtiff pam-devel libicu libicu-devel gettext-devel libaio-devel libaio libgcc libstdc++ libstdc++-devel unixODBC unixODBC-devel numactl-devel glibc-headers sudo bzip2 mlocate flex lrzsz sysstat lsof setuptool system-config-network-tui system-config-firewall-tui ntsysv ntp pv lz4 dos2unix unix2dos rsync dstat iotop innotop mytop telnet iftop expect cmake nc gnuplot screen xorg-x11-utils xorg-x11-xinit rdate bc expat-devel compat-expat1 tcpdump sysstat man nmap curl lrzsz elinks finger bind-utils traceroute mtr ntpdate zip unzip vim wget net-tools

下载依赖包 (除了nginx节点,其他节点都要安装)

mkdir /root/tools/
cd /root/tools
wget http://nginx.org/download/nginx-1.18.0.tar.gz
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz
wget https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz
wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz


#为了保证文章可用性,本次软件包已经进行备份,下载地址如下
mkdir /root/tools/
cd /root/tools
wget http://down.i4t.com/fdfs/v6.6/nginx-1.18.0.tar.gz
wget http://down.i4t.com/fdfs/v6.6/V1.0.43.tar.gz
wget http://down.i4t.com/fdfs/v6.6/V6.06.tar.gz
wget http://down.i4t.com/fdfs/v6.6/V1.22.tar.gz



#解压
cd /root/tools
tar xf nginx-1.18.0.tar.gz 
tar xf V1.0.43.tar.gz 
tar xf V1.22.tar.gz 
tar xf V6.06.tar.gz 

安装libfastcommon (除了nginx节点,其他节点都要安装)

cd /root/tools/libfastcommon-1.0.43
./make.sh 
./make.sh install

安装FastDFS (除了nginx节点,其他节点都要安装)

cd /root/tools/fastdfs-6.06/
./make.sh 
./make.sh install

拷贝配置文件 (tracker01 02节点)

[root@tracker01 fastdfs-6.06]# cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf     #tracker节点
[root@01 fastdfs-6.06]# cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf      #客户端文件(测试使用)
[root@01 fastdfs-6.06]# cp /root/tools/fastdfs-6.06/conf/http.conf /etc/fdfs/      #nginx配置文件
[root@01 fastdfs-6.06]# cp /root/tools/fastdfs-6.06/conf/mime.types /etc/fdfs/     #nginx配置文件

配置tracker 01节点

这里可以先配置一台节点,没有问题在启动另外的节点

创建tracker数据存储及日志目录 (需要在tracker节点执行)

mkdir /data/tracker/ -p 

修改配置文件 (tracker 01节点执行)

cat >/etc/fdfs/tracker.conf <<EOF
disabled = false
bind_addr =
port = 22122
connect_timeout = 5
network_timeout = 60
base_path = /data/tracker
max_connections = 1024
accept_threads = 1
work_threads = 4
min_buff_size = 8KB
max_buff_size = 128KB
store_lookup = 0
store_server = 0
store_path = 0
download_server = 0
reserved_storage_space = 20%
log_level = info
run_by_group=
run_by_user =
allow_hosts = *
sync_log_buff_interval = 1
check_active_interval = 120
thread_stack_size = 256KB
storage_ip_changed_auto_adjust = true
storage_sync_file_max_delay = 86400
storage_sync_file_max_time = 300
use_trunk_file = false 
slot_min_size = 256
slot_max_size = 1MB
trunk_alloc_alignment_size = 256
trunk_free_space_merge = true
delete_unused_trunk_files = false
trunk_file_size = 64MB
trunk_create_file_advance = false
trunk_create_file_time_base = 02:00
trunk_create_file_interval = 86400
trunk_create_file_space_threshold = 20G
trunk_init_check_occupying = false
trunk_init_reload_from_binlog = false
trunk_compress_binlog_min_interval = 86400
trunk_compress_binlog_interval = 86400
trunk_compress_binlog_time_base = 03:00
trunk_binlog_max_backups = 7
use_storage_id = false
storage_ids_filename = storage_ids.conf
id_type_in_filename = id
store_slave_file_use_link = false
rotate_error_log = false
error_log_rotate_time = 00:00
compress_old_error_log = false
compress_error_log_days_before = 7
rotate_error_log_size = 0
log_file_keep_days = 0
use_connection_pool = true
connection_pool_max_idle_time = 3600
http.server_port = 8080
http.check_alive_interval = 30
http.check_alive_type = tcp
http.check_alive_uri = /status.html
EOF

启动tracker

[root@01 fastdfs-6.06]# /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start

配置tracker02节点

拷贝配置文件

scp -r /etc/fdfs/tracker.conf root@192.168.31.102:/etc/fdfs/
ssh root@192.168.31.102 mkdir /data/tracker/ -p 

tracker02启动tracker

[root@02 fastdfs-6.06]# /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start

检查启动状态

netstat -lntup|grep 22122
tcp        0      0 0.0.0.0:22122           0.0.0.0:*               LISTEN      108126/fdfs_tracker

如果启动失败可以查看tracker报错

tail -f /data/tracker/logs/trackerd.log

接下来编辑启动脚本

cat > /usr/lib/systemd/system/tracker.service <<EOF
[Unit]
Description=The FastDFS File server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
ExecStart=/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
ExecStop=/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf stop
ExecRestart=/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

[Install]
WantedBy=multi-user.target
EOF


$ systemctl daemon-reload
$ systemctl start tracker
$ systemctl enable tracker
$ systemctl status tracker

#需要先手动kill 掉tracker

storage 01-02节点配置

storage01节点和02节点配置相同,storage03和storage04配置相同

storage01和storage02节点属于group1组

创建storage 数据存储目录

mkdir /data/fastdfs_data -p

修改配置文件

cat >/etc/fdfs/storage.conf<<EOF
disabled = false
group_name = group1
bind_addr =
client_bind = true
port = 23000
connect_timeout = 5
network_timeout = 60
heart_beat_interval = 30
stat_report_interval = 60
base_path = /data/fastdfs_data
max_connections = 1024
buff_size = 256KB
accept_threads = 1
work_threads = 4
disk_rw_separated = true
disk_reader_threads = 1
disk_writer_threads = 1
sync_wait_msec = 50
sync_interval = 0
sync_start_time = 00:00
sync_end_time = 23:59
write_mark_file_freq = 500
disk_recovery_threads = 3
store_path_count = 1
store_path0 = /data/fastdfs_data
subdir_count_per_path = 256
tracker_server = 192.168.31.101:22122
tracker_server = 192.168.31.102:22122
log_level = info
run_by_group =
run_by_user =
allow_hosts = *
file_distribute_path_mode = 0
file_distribute_rotate_count = 100
fsync_after_written_bytes = 0
sync_log_buff_interval = 1
sync_binlog_buff_interval = 1
sync_stat_file_interval = 300
thread_stack_size = 512KB
upload_priority = 10
if_alias_prefix =
check_file_duplicate = 0
file_signature_method = hash
key_namespace = FastDFS
keep_alive = 0
use_access_log = false
rotate_access_log = false
access_log_rotate_time = 00:00
compress_old_access_log = false
compress_access_log_days_before = 7
rotate_error_log = false
error_log_rotate_time = 00:00
compress_old_error_log = false
compress_error_log_days_before = 7
rotate_access_log_size = 0
rotate_error_log_size = 0
log_file_keep_days = 0
file_sync_skip_invalid_record = false
use_connection_pool = true
connection_pool_max_idle_time = 3600
compress_binlog = true
compress_binlog_time = 01:30
check_store_path_mark = true
http.domain_name =
http.server_port = 80
EOF

#注意: 需要修改tracker_server地址,多个节点多复制几行,一个节点写一行就可以。 不建议单节点使用localhost

配置启动文件

cat >/usr/lib/systemd/system/storage.service <<EOF

[Unit]
Description=The FastDFS File server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
ExecStart=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
ExecStop=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf stop
ExecRestart=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl start storage
systemctl status storage
systemctl enable storage

检查启动状态

netstat -lntup|grep 23000

如果出现启动失败,可以到设置的目录查看一下log

tail -f /data/fastdfs_data/logs/storaged.log

storage 02-03节点配置

storage03和storage04节点属于group2组

基本流程不变这里只说明需要修改的地方

在storage03-storage-04节点同步执行

创建storage 数据存储目录
mkdir /data/fastdfs_data -p

修改配置文件
cat >/etc/fdfs/storage.conf<<EOF
disabled = false
group_name = group2
bind_addr =
client_bind = true
port = 23000
connect_timeout = 5
network_timeout = 60
heart_beat_interval = 30
stat_report_interval = 60
base_path = /data/fastdfs_data
max_connections = 1024
buff_size = 256KB
accept_threads = 1
work_threads = 4
disk_rw_separated = true
disk_reader_threads = 1
disk_writer_threads = 1
sync_wait_msec = 50
sync_interval = 0
sync_start_time = 00:00
sync_end_time = 23:59
write_mark_file_freq = 500
disk_recovery_threads = 3
store_path_count = 1
store_path0 = /data/fastdfs_data
subdir_count_per_path = 256
tracker_server = 192.168.31.101:22122
tracker_server = 192.168.31.102:22122
log_level = info
run_by_group =
run_by_user =
allow_hosts = *
file_distribute_path_mode = 0
file_distribute_rotate_count = 100
fsync_after_written_bytes = 0
sync_log_buff_interval = 1
sync_binlog_buff_interval = 1
sync_stat_file_interval = 300
thread_stack_size = 512KB
upload_priority = 10
if_alias_prefix =
check_file_duplicate = 0
file_signature_method = hash
key_namespace = FastDFS
keep_alive = 0
use_access_log = false
rotate_access_log = false
access_log_rotate_time = 00:00
compress_old_access_log = false
compress_access_log_days_before = 7
rotate_error_log = false
error_log_rotate_time = 00:00
compress_old_error_log = false
compress_error_log_days_before = 7
rotate_access_log_size = 0
rotate_error_log_size = 0
log_file_keep_days = 0
file_sync_skip_invalid_record = false
use_connection_pool = true
connection_pool_max_idle_time = 3600
compress_binlog = true
compress_binlog_time = 01:30
check_store_path_mark = true
http.domain_name =
http.server_port = 80
EOF


#配置启动文件
cat >/usr/lib/systemd/system/storage.service <<EOF

[Unit]
Description=The FastDFS File server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
ExecStart=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
ExecStop=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf stop
ExecRestart=/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl start storage
systemctl status storage
systemctl enable storage


#检查启动状态
netstat -lntup|grep 23000

如果出现systemctl启动失败,可以使用命令启动,在根据日志进行查看。 大概启动时间为10s

#storage启动、停止、重启命令
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf stop
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

所有节点storage启动完毕后进行检查,是否可以获取到集群信息 (刚创建的集群比较慢,稍等一会。需要等待状态为ACTIVE即可)

#在任意节点storage节点执行命令都可以,获取结果应该如下
[root@storage01 fdfs]#  fdfs_monitor /etc/fdfs/storage.conf list

[2020-07-03 01:15:25] DEBUG - base_path=/data/fastdfs_data, connect_timeout=5, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=1, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0

server_count=2, server_index=1   

tracker server is 192.168.31.102:22122     #tracker server处理本次命令的节点

group count: 2                            #group组数量

Group 1:                                   #group1组信息
group name = group1
disk total space = 17,394 MB
disk free space = 13,758 MB
trunk free space = 0 MB
storage server count = 2
active server count = 2
storage server port = 23000
storage HTTP port = 80
store path count = 1
subdir count per path = 256
current write server index = 0
current trunk file id = 0

    Storage 1:                                   #storage1节点信息
        id = 192.168.31.103
        ip_addr = 192.168.31.103  ACTIVE         #storage节点状态
        http domain = 
        version = 6.06                           #fdfs 版本
        join time = 2020-07-03 01:08:29          #加入集群时间
        up time = 2020-07-03 01:08:29
        total storage = 17,394 MB
        free storage = 14,098 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000
        storage_http_port = 80
        current_write_path = 0
        source storage id = 192.168.31.104
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 1
        ...............省略号............................
        last_heart_beat_time = 2020-07-03 01:15:18
        last_source_update = 1970-01-01 08:00:00
        last_sync_update = 1970-01-01 08:00:00
        last_synced_timestamp = 1970-01-01 08:00:00 
    Storage 2:                                   #storage2节点信息
        id = 192.168.31.104                      #storage 节点IP
        ip_addr = 192.168.31.104  ACTIVE         #storage 节点状态
        http domain = 
        version = 6.06                          #storage 节点版本
        join time = 2020-07-03 01:08:26         #加入时间
        up time = 2020-07-03 01:08:26
        total storage = 17,394 MB
        free storage = 13,758 MB
        upload priority = 10
        store_path_count = 1
        ...............省略号............................
        last_heart_beat_time = 2020-07-03 01:15:17
        last_source_update = 1970-01-01 08:00:00
        last_sync_update = 1970-01-01 08:00:00
        last_synced_timestamp = 1970-01-01 08:00:00 

Group 2:                                         #group2集群信息
group name = group2
disk total space = 17,394 MB
disk free space = 15,538 MB
trunk free space = 0 MB
storage server count = 2
active server count = 2
storage server port = 23000
storage HTTP port = 80
store path count = 1
subdir count per path = 256
current write server index = 0
current trunk file id = 0

    Storage 1:                                     #storage1节点信息
        id = 192.168.31.105
        ip_addr = 192.168.31.105  ACTIVE
        http domain = 
        version = 6.06
        join time = 2020-07-03 01:13:42
        up time = 2020-07-03 01:13:42
        total storage = 17,394 MB
        free storage = 15,538 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000                   #storage端口
        storage_http_port = 80
        current_write_path = 0
        source storage id = 
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 1
        ...............省略号............................
        last_heart_beat_time = 2020-07-03 01:15:22
        last_source_update = 1970-01-01 08:00:00
        last_sync_update = 1970-01-01 08:00:00
        last_synced_timestamp = 1970-01-01 08:00:00 
    Storage 2:
        id = 192.168.31.106
        ip_addr = 192.168.31.106  ACTIVE
        http domain = 
        version = 6.06
        join time = 2020-07-03 01:14:05
        up time = 2020-07-03 01:14:05
        total storage = 17,394 MB
        free storage = 15,538 MB
        upload priority = 10
        store_path_count = 1
        subdir_count_per_path = 256
        storage_port = 23000
        storage_http_port = 80
        current_write_path = 0
        source storage id = 192.168.31.105
        if_trunk_server = 0
        connection.alloc_count = 256
        connection.current_count = 1
        connection.max_count = 1
        total_upload_count = 0
        ...............省略号............................
        total_file_write_count = 0
        success_file_write_count = 0
        last_heart_beat_time = 2020-07-03 01:15:10
        last_source_update = 1970-01-01 08:00:00
        last_sync_update = 1970-01-01 08:00:00
        last_synced_timestamp = 1970-01-01 08:00:00 

配置client

这里在tracker01节点配置celient客户端 (其他节点可不配置,client.conf为可选配置)

mkdir -p /data/fdfs_client/logs  #日志存放路径

cat >/etc/fdfs/client.conf <<EOF
connect_timeout = 5
network_timeout = 60
base_path = /data/fdfs_client/logs
tracker_server = 192.168.31.101:22122
tracker_server = 192.168.31.102:22122
log_level = info
use_connection_pool = false
connection_pool_max_idle_time = 3600
load_fdfs_parameters_from_tracker = false
use_storage_id = false
storage_ids_filename = storage_ids.conf
http.tracker_server_port = 80
EOF

#需要修改tracker_server地址

上传文件测试,这里的文件是init.yaml

[root@01 ~]# echo "test" >init.yaml
[root@01 ~]# fdfs_upload_file /etc/fdfs/client.conf init.yaml
group2/M00/00/00/wKgfaV7-GG2AQcpMAAAABTu5NcY98.yaml

Storage节点安装Nginx

所有storage节点mod_fastdfs.conf配置如下

cat >/etc/fdfs/mod_fastdfs.conf <<EOF
connect_timeout=2
network_timeout=30
base_path=/tmp
load_fdfs_parameters_from_tracker=true
storage_sync_file_max_delay = 86400
use_storage_id = false
storage_ids_filename = storage_ids.conf
tracker_server=192.168.31.101:22122
tracker_server=192.168.31.102:22122
storage_server_port=23000
url_have_group_name = true
store_path_count=1
log_level=info
log_filename=
response_mode=proxy
if_alias_prefix=
flv_support = true
flv_extension = flv
group_count = 2
#include http.conf

[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs_data

[group2]
group_name=group2
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs_data
EOF

拷贝相关依赖 (以下是所有storage节点安装)

cp /root/tools/fastdfs-6.06/conf/http.conf /etc/fdfs/
cp /root/tools/fastdfs-6.06/conf/mime.types /etc/fdfs/

安装Nginx依赖包

yum install -y gcc glibc gcc-c++ prce-devel openssl-devel pcre-devel lua-devel libxml2 libxml2-devel libxslt-devel  perl-ExtUtils-Embed   GeoIP GeoIP-devel GeoIP-data zlib zlib-devel openssl  pcre pcre-devel gcc g++ gcc-c++ gd-devel

创建nginx用户

useradd -s /sbin/nologin nginx -M

编译nginx

cd /root/tools/nginx-1.18.0
./configure --prefix=/usr/local/nginx-1.18 --with-http_ssl_module --user=nginx --group=nginx  --with-http_sub_module  --add-module=/root/tools/fastdfs-nginx-module-1.22/src

make && make install

ln -s /usr/local/nginx-1.18 /usr/local/nginx

修改Nginx配置文件

cat > /usr/local/nginx/conf/nginx.conf <<EOF
worker_processes  1;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;


    server {
        listen       8888;
        server_name  localhost;

        location ~/group[0-9]/M00 {
            root /data/fastdfs_data;
            ngx_fastdfs_module;
        }
    }

}
EOF

启动nginx

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx

在storage节点上8888的请求且有group的都转给ngx_fastdfs_module插件处理

接下来我们手动上传两张图片进行测试

[root@tracker01 ~]# fdfs_upload_file /etc/fdfs/client.conf abcdocker.png 
group1/M00/00/00/wKgfZ17-JkKAYX-SAABc0HR4eEs313.png

[root@tracker01 ~]# fdfs_upload_file /etc/fdfs/client.conf i4t.jpg 
group2/M00/00/00/wKgfal7-JySABmgLAABdMoE-LPo504.jpg

目前我们tracker属于轮训机制,会轮训group1和group2;具体使用参数可以参考下面的文章

接下来我们可以通过浏览器访问,不同的组对应不同的项目,FastDFS集群可以有多个组,但是每台机器只可以有一个storage

http://storage1节点:8888/group1/M00/00/00/wKgfZ17-JkKAYX-SAABc0HR4eEs313.png
http://storage1节点:8888/group2/M00/00/00/wKgfal7-JySABmgLAABdMoE-LPo504.jpg

经过我的测试,即使我们把图片上传到group1中,在group2上面直接访问也可以访问成功,但是在group2的存储目录并没有找到图片文件。原因如下

#Nginx日志
192.168.31.174 - - [03/Jul/2020:03:03:31 +0800] "GET /group2/M00/00/00/wKgfaF7-JyKAYde2AABdMoE-LPo633.jpg HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"

为何我们其他storage节点也可以访问,原因是nginx中fastdfs-nginx-module模块可以重定向文件连接到源服务器取文件

补充: FastDFS常用命令参数

#查看集群状态
fdfs_monitor /etc/fdfs/storage.conf

#上传
fdfs_upload_file /etc/fdfs/client.conf abcdocker.png 
#下载
fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgfZ17-JkKAYX-SAABc0HR4eEs313.png
#查看文件属性
fdfs_file_info /etc/fdfs/client.conf group1/M00/00/00/wKgfZ17-JkKAYX-SAABc0HR4eEs313.png

#删除文件
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/wKgfZ17-JkKAYX-SAABc0HR4eEs313.png

#删除一个storage
/usr/local/bin/fdfs_monitor /etc/fdfs/storage.conf delete group2 192.168.31.105

Tracker配置高可用

在tracker上安装的nginx主要为了提供http访问的反向代理、负载均衡和缓存服务

这里我们tracker01 02同时进行安装即可

#下载nginx依赖包
mkdir /root/tools -p
cd /root/tools
wget http://down.i4t.com/ngx_cache_purge-2.3.tar.gz
wget http://down.i4t.com/fdfs/v6.6/nginx-1.18.0.tar.gz
tar xf ngx_cache_purge-2.3.tar.gz
tar xf nginx-1.18.0.tar.gz

#创建nginx用户
useradd -s /sbin/nologin -M nginx

#编译nginx
cd /root/tools/nginx-1.18.0
./configure --prefix=/usr/local/nginx-1.18 --with-http_ssl_module --user=nginx --group=nginx  --with-http_sub_module --add-module=/root/tools/ngx_cache_purge-2.3

make && make install

ln -s /usr/local/nginx-1.18 /usr/local/nginx

nginx安装完毕,接下来配置nginx.conf

tracker 中nginx节点可以不是80,我这里以80位代表

mkdir /data/nginx_cache -p

$ vim /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 300m;
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 16k;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 128k;
    proxy_cache_path /data/nginx_cache keys_zone=http-cache:100m;

upstream fdfs_group1 {
    server 192.168.31.103:8888 weight=1 max_fails=2 fail_timeout=30s;
    server 192.168.80.104:8888 weight=1 max_fails=2 fail_timeout=30s;
}
upstream fdfs_group2 {
    server 192.168.31.105:8888 weight=1 max_fails=2 fail_timeout=30s;
    server 192.168.31.106:8888 weight=1 max_fails=2 fail_timeout=30s;
}


    server {
        listen       80;
        server_name  localhost;
        location /group1/M00 {
            proxy_next_upstream http_502 http_504 error timeout invalid_header;
            proxy_cache http-cache;
            proxy_cache_valid  200 304 12h;
            proxy_cache_key $uri$is_args$args;
            proxy_pass http://fdfs_group1;
            expires 30d;
        }

        location /group2/M00 {
            proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_cache http-cache;
            proxy_cache_valid 200 304 12h;
            proxy_cache_key $uri$is_args$args;
            proxy_pass http://fdfs_group2;
            expires 30d;
        }

    }
 }

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx 

此时访问tracker01节点和tracker02节点应该都没有问题

http://192.168.31.101/group1/M00/00/00/wKgfaF7-JyKAYde2AABdMoE-LPo633.jpg
http://192.168.31.101/group2/M00/00/00/wKgfaF7-JyKAYde2AABdMoE-LPo633.jpg

http://192.168.31.102/group2/M00/00/00/wKgfaF7-JyKAYde2AABdMoE-LPo633.jpg
http://192.168.31.102/group2/M00/00/00/wKgfaF7-JyKAYde2AABdMoE-LPo633.jpg

效果图如下

搭建分布式文件系统FastDFS集群


Nginx代理安装

通过上面的步骤,已经可以使用storage节点和tracker节点进行访问,但是为了解决统一管理和tracker高可用,我们还需要使用nginx在去代理tracker

#nginx安装和上面一样,我这里就只更改nginx.conf文件,nginx代理不需要缓存模块,普通安装即可

$ vim /usr/local/nginx/conf/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

upstream fastdfs_tracker {
        server 192.168.31.101:80 weight=1 max_fails=2 fail_timeout=30s;
        server 192.168.31.102:80 weight=1 max_fails=2 fail_timeout=30s;
}
    server {
        listen       80;
        server_name  localhost;

        location / {
        proxy_pass http://fastdfs_tracker/;
        }

    }
}

最后我们在tracker01节点上,测试nginx代理是否都可以访问成功

[root@tracker01 ~]# fdfs_upload_file /etc/fdfs/client.conf i4t.jpg 
group1/M00/00/00/wKgfZ17-Oa2AMuRqAABdMoE-LPo686.jpg

[root@tracker01 ~]# fdfs_upload_file /etc/fdfs/client.conf i4t.jpg 
group2/M00/00/00/wKgfaV7-Oa6ANXGLAABdMoE-LPo066.jpg

访问查看
[root@tracker01 ~]# curl 192.168.31.100/group1/M00/00/00/wKgfZ17-Oa2AMuRqAABdMoE-LPo686.jpg -I
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 02 Jul 2020 19:49:49 GMT
Content-Type: image/jpeg
Content-Length: 23858
Connection: keep-alive
Last-Modified: Thu, 02 Jul 2020 19:46:53 GMT
Expires: Sat, 01 Aug 2020 19:49:49 GMT
Cache-Control: max-age=2592000
Accept-Ranges: bytes

[root@tracker01 ~]# curl 192.168.31.100/group2/M00/00/00/wKgfaV7-Oa6ANXGLAABdMoE-LPo066.jpg -I
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 02 Jul 2020 19:50:17 GMT
Content-Type: image/jpeg
Content-Length: 23858
Connection: keep-alive
Last-Modified: Thu, 02 Jul 2020 19:46:54 GMT
Expires: Sat, 01 Aug 2020 19:50:17 GMT
Cache-Control: max-age=2592000
Accept-Ranges: bytes

 

上一篇:fastDFS安装时,./make.sh编译时出错找不到./make.sh: line 99: perl: command not found


下一篇:FastDFS 磁盘空间不足(tracker_query_storage fail,error no : 28,error info : No space left on device)