FastDFS

FastDFS的作者余庆在其 GitHub 上是这样描述的:“FastDFS is an open source high performance distributed file system. It's major functions include: file storing, file syncing and file accessing (file uploading and file downloading), and it can resolve the high capacity and load balancing problem. FastDFS should meet the requirement of the website whose service based on files such as photo sharing site and video sharing site” ,意思说,FastDFS是一个开源的高性能分布式文件系统。其主要功能包括:文件存储、文件同步和文件访问(文件上传和文件下载),它可以解决高容量和负载平衡问题。FastDFS应满足基于照片共享站点和视频共享站点等文件的网站的服务要求。

FastDFS 有两个角色:跟踪器(Tracker)和存储器(Storage)。Tracker 负责文件访问的调度和负载平衡。Storage 存储文件及其功能是文件管理,包括:文件存储、文件同步、提供文件访问接口。它还管理元数据,这些元数据是表示为文件的键值对的属性。TrackerStorage 节点都可以由一台或多台服务器构成。这些服务器均可以随时增加或下线而不会影响线上服务,当然各个节点集群至少需要一台服务 Running。注意,其中 Tracker 集群中的所有服务器都是对等的(P2P),可以根据服务器的压力情况随时增加或减少。

此外,官网还存储系统做了详尽的说明,为了支持大容量,Storage 节点采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台 Storage 服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。关于卷或组的概念暂且不要过多深入,后面的安装部署中会后详细的说明。

在FastDFS中,文件的标识由两部分组成:卷名和文件名。

环境说明

  • 操作系统:Centos Linux release 7.2.1511
  • 系统磁盘: 274G
  • 挂在磁盘:3.7T * 12
  • CPU:32 (Intel(R) Xeon(R) )
  • Memory:8G

架构设计

图1 DFS架构图

工作方式:客户端向 tracker 发出请求,然后 tracker 从 storage 节点拿到源数据,返还给客户端,然后客户端根据源数据再去请求 storage 节点。

图2 高可用DFS架构图(红色虚线部分另外讨论)

概要精简

1.核心系统只有两个角色,tracker server和storage server。

2.所有跟踪器服务器都是对等的,不存在 Master-Slave 关系(图中 Tracker-leader 需另行讨论,目前只需要明白 tracker 是 P2P)。

3.存储服务器采用分组方式,同组内存储服务器上的文件完全相同。

4.不同组的 storage server 之间不会相互通信,相同组之间会进行同步。

5.由 storage server 主动向 tracker server 报告状态信息,每个 tracker server 都会记录 storage server 的信息。

6.如果开启了 trunk 功能,tracker 服务协调 storage 选举 trunk-server。

集群部署

准备环境

表1 软件列表及版本

名称 说明 链接
CentOS 7.x(安装系统)
libfastcommon FastDFS分离出的一些公用函数包 libfastcommon V1.0.39
FastDFS FastDFS本体 FastDFS V5.11
fastdfs-nginx-module FastDFS和nginx的关联模块,解决组内同步延迟问题 fastdfs-nginx-module V1.20
nginx nginx 1.12.2(CentOS 7 下YUM可以安装的最新版本) nginx 1.12.2

Note: 在google浏览器中,点击上面链接下载和复制链接下载的文件名称不相同,google会根据上面的文本信息重命名。

表2 服务器IP、服务分配、端口规划表

名称 IP地址 应用服务 端口
A机器
10.58.10.136 tracker 22122
10.58.10.136 storage-group1 23000
10.58.10.136 storage-group2 33000
10.58.10.136 libfastcommon -
10.58.10.136 nginx 8888
10.58.10.136 fastdfs-nginx-module -
B机器
10.58.10.137 tracker 22122
10.58.10.137 storage-group1 23000
10.58.10.137 storage-group3 43000
10.58.10.137 libfastcommon -
10.58.10.137 nginx 8888
10.58.10.137 fastdfs-nginx-module -
C机器
10.58.10.138 tracker 22122
10.58.10.138 storage-group2 33000
10.58.10.138 storage-group23 43000
10.58.10.138 libfastcommon -
10.58.10.138 nginx 8888
10.58.10.138 fastdfs-nginx-module -

在安装之前必须说明:

1.记得给下面用到的存储目录(日志、数据、pid文件等)授权可读可写权限;

2.下面所有的配置文件中由于说明,加了注释,请务必在配置的时候把配置项后面以“#”开头的注释删掉。

初始化环境

# 安装编译环境
$ yum groups install Development Tools -y
$ yum install perl -y
$ yum -y install redhat-rpm-config.noarch
$ yum -y install gd-devel
$ yum -y install perl-devel perl-ExtUtils-Embed
$ yum -y install pcre-devel
$ yum -y install openssl openssl-devel
$ yum -y install gcc-c++ autoconf automake
$ yum install -y zlib-devel
$ yum -y install libxml2 libxml2-dev
$ yum -y install libxslt-devel
$ yum -y install GeoIP GeoIP-devel GeoIP-data
$ yum install gperftools -y

安装libfastcommon

在A、B、C三台机器上分别执行下面的操作:

$ tar -zxvf libfastcommon-1.0.39.tar.gz
$ cd libfastcommon-1.0.39/
$ ./make.sh
$ ./make.sh install

libfastcommon 安装在了 /usr/lib64/libfastcommon.so。需要注意新老版本,新版本在安装之后自动会将 libfastcommon.so 通过软连接链接到 /usr/local/lib 目录下面。如果是老版本,则需要手动建立:

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

如果有 libfdfsclient.so,则也可以把libfdfsclient.so加入到 /usr/local/lib 中:

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

Note:最好自己通过命令 ls | grep libfastcommon/usr/lib//usr/local/lib 查看确认是否链接成功。

安装tracker

在 A、B、C 三台机器上分别执行下面操作:

$ mkdir -p /data/fastdfs/tracker
$ tar -zxvf fastdfs-5.11.tar.gz
$ cd fastdfs-5.11/
$ ./make.sh
$ ./make.sh install
$ # 配置文件准备
$ cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf #tracker节点

修改tracker的配置文件:

$ vim /etc/fdfs/tracker.conf
$ #需要修改的内容如下
max_connections=1024 #默认256,最大连接数
port=22122 # tracker 服务器端口(默认 22122,一般不修改)
base_path=/data/fastdfs/tracker # 存储日志和数据的根目录

增加 tracker.service 服务,可使用 systemctl 执行服务的启动、重启、停止等操作,也可设置开机自动重启。

$ #编辑启动文件
$ vim /usr/lib/systemd/system/fastdfs-tracker.service
[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

保存 /usr/lib/systemd/system/fastdfs-tracker.service 文件并退出 vim 编辑器,我们执行下面操作启动 Fastdfs Tracker 服务:

$ systemctl daemon-reload
$ systemctl enable fastdfs-tracker.service
$ systemctl start fastdfs-tracker.service

tracker 服务启动结束后,我们通过下面命令查看端口是否正常:

$ netstat -tulnp|grep 22122 #查看服务是否启动,端口是否打开

安装sorage

安装 tracker 的时候已经解压过了则可以不执行此步骤。

$ tar -zxvf fastdfs-5.11.tar.gz
$ cd fastdfs-5.11/
$ ./make.sh
$ ./make.sh install
A 机器(group1/group2)

在 fastdfs-5.11 目录下面复制 storage 的配置文件(复制两份):

$ sudo mkdir -p /data/fastdfs/storage/group1
$ sudo mkdir -p /data/fastdfs/storage/group2
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group1.conf #storage节点的group1组
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group2.conf #storage节点的group1组
$ sudo cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用

根据架构设计,我们依次修改上面的三个文件:

  • 修改 group1 的配置文件:/etc/fdfs/storage-group1.conf
$ sudo vim /etc/fdfs/storage-group1.conf
#需要修改的内容如下
group_name=group1
port=23000 # storage 服务端口(默认 23000)
base_path=/data/fastdfs/storage/group1 # 数据和日志文件存储根目录
store_path_count=6
store_path0=/data01/fastdfs # group1 的第一个存储目录
store_path1=/data02/fastdfs # group1 的第二个存储目录
store_path2=/data03/fastdfs # group1 的第三个存储目录
store_path3=/data04/fastdfs # group1 的第四个存储目录
store_path4=/data05/fastdfs # group1 的第五个存储目录
store_path5=/data06/fastdfs # group1 的第六个存储目录
tracker_server=10.58.10.136:22122 # tracker 服务器IP和端口
tracker_server=10.58.10.137:22122 # tracker 服务器IP和端口
tracker_server=10.58.10.138:22122 # tracker 服务器IP和端口
http.server_port=8888 # http 访问文件的端口(默认 8888,看情况修改,和nginx 中保持一致)
  • 修改 group2 的配置文件:/etc/fdfs/storage-group2.conf
$ sudo vim /etc/fdfs/storage-group2.conf
#需要修改的内容如下
group_name=group2
port=33000 # storage 服务端口(默认 23000,修改为 33000)
base_path=/data/fastdfs/storage/group2 # 数据和日志文件存储根目录
store_path_count=6
store_path0=/data07/fastdfs # group2 的第一个存储目录
store_path1=/data08/fastdfs # group2 的第二个存储目录
store_path2=/data09/fastdfs # group2 的第三个存储目录
store_path3=/data10/fastdfs # group2 的第四个存储目录
store_path4=/data11/fastdfs # group2 的第五个存储目录
store_path5=/data12/fastdfs # group2 的第六个存储目录
tracker_server=10.58.10.136:22122 # tracker 服务器 IP 和端口
tracker_server=10.58.10.137:22122 # tracker 服务器 IP 和端口
tracker_server=10.58.10.138:22122 # tracker 服务器 IP 和端口
http.server_port=8888 # http 访问文件的端口(默认 8888,看情况修改,和nginx 中保持一致)
  • 修改client的配置文件:/etc/fdfs/client.conf
$ sudo vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/data/fastdfs/client
tracker_server=10.58.10.136:22122 # tracker 服务器 IP 和端口
tracker_server=10.58.10.137:22122 # tracker 服务器 IP 和端口
tracker_server=10.58.10.138:22122 # tracker 服务器 IP 和端口
  • 修改好以上三个配置文件之后,我们制作启动 service:

fastdfs-storage-group1.service

$ vim /usr/lib/systemd/system/fastdfs-storage-group1.service
# 编辑启动文件
[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-group1.conf start
ExecStop=/usr/bin/fdfs_storaged /etc/fdfs/storage-group1.conf stop
ExecRestart=/usr/bin/fdfs_storaged /etc/fdfs/storage-group1.conf restart [Install]
WantedBy=multi-user.target

fastdfs-storage-group2.service

$ vim /usr/lib/systemd/system/fastdfs-storage-group2.service
# 编辑启动文件
[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-group2.conf start
ExecStop=/usr/bin/fdfs_storaged /etc/fdfs/storage-group2.conf stop
ExecRestart=/usr/bin/fdfs_storaged /etc/fdfs/storage-group2.conf restart [Install]
WantedBy=multi-user.target
  • Storage 的 service 制作好只好,我们启动 Storage 的两个服务:
$ systemctl daemon-reload
$ systemctl enable fastdfs-storage-group1.service
$ systemctl start fastdfs-storage-group1.service

启动过程可能因为某些权限或配置书写错误的问题,会出现启动失败的情况,可通过 systemctl status fastdfs-storage-group1.service 查看该服务的状态,同时结合logs(日志文件在 /data/fastdfs/storage/group1/logs/目录下面)排查,可以快速定位问题。如果出现一些异常情况,也可以看看后面的采坑部分,看看有没有期望的结果。

$ netstat -tulnp #查看服务是否启动,端口是否打开(23000,33000)
  • 服务起来之后,我们可以查看Fastdfs的集群状态:
#查看集群状态
$ fdfs_monitor /etc/fdfs/storage-group1.conf list

控制台打印出如下信息,说明成功了:

[2018-11-06 00:00:00] DEBUG - base_path=/data/fastdfs/storage/group1, connect_timeout=30, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0
server_count=3, server_index=0
tracker server is 10.58.10.136:22122,10.58.10.137:22122,10.58.10.138:22122
group count: 2
Group 1:
...
  • 通过客户端测试上传文件
#保存后测试,返回 ID 表示成功 如:group1/M00/00/00/xx.txt
$ fdfs_upload_file /etc/fdfs/client.conf test.txt
B 机器(group1/group3)

配置过程与 A 机器类似,需要修改以下几个点:

  • 创建目录及复制配置文件。
$ sudo mkdir -p /data/fastdfs/storage/group1
$ sudo mkdir -p /data/fastdfs/storage/group3
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group1.conf #storage节点的group1组
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group3.conf #storage节点的group3组
$ sudo cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用
  • 修改 group3 的配置文件/etc/fdfs/storage-group3.conf,group1 的配置内容和 A 的保持一致。
$ sudo vim /etc/fdfs/storage-group3.conf
#需要修改的内容如下
group_name=group3
port=43000 # storage服务端口(默认23000,修改为43000)
base_path=/data/fastdfs/storage/group3 # 数据和日志文件存储根目录
store_path_count=6
store_path0=/data07/fastdfs # group3的第一个存储目录
store_path1=/data08/fastdfs # group3的第二个存储目录
store_path2=/data09/fastdfs # group3的第三个存储目录
store_path3=/data10/fastdfs # group3的第四个存储目录
store_path4=/data11/fastdfs # group3的第五个存储目录
store_path5=/data12/fastdfs # group3的第六个存储目录
tracker_server=10.58.10.136:22122 # tracker服务器IP和端口
tracker_server=10.58.10.137:22122 # tracker服务器IP和端口
tracker_server=10.58.10.138:22122 # tracker服务器IP和端口
http.server_port=8888 # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
  • client 的配置文件和 A 机器一致,此处不做重复。
  • 制作启动 group3 的 service,fastdfs-storage-group1.service和 A 机器一致,复制即可。
$ vim /usr/lib/systemd/system/fastdfs-storage-group3.service
# 编辑启动文件
[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-group3.conf start
ExecStop=/usr/bin/fdfs_storaged /etc/fdfs/storage-group3.conf stop
ExecRestart=/usr/bin/fdfs_storaged /etc/fdfs/storage-group3.conf restart [Install]
WantedBy=multi-user.target
  • 执行启动脚本,直到 fastdfs-storage-group1.servicefastdfs-storage-group3.service 服务起来即可。
C 机器(group2/group3)

配置过程与 A 机器类似,需要修改以下几个点:

  • 创建目录及复制配置文件。
$ sudo mkdir -p /data/fastdfs/storage/group2
$ sudo mkdir -p /data/fastdfs/storage/group3
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group2.conf #storage节点的group1组
$ sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage-group3.conf #storage节点的group3组
$ sudo cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用
  • 修改 group2 的配置文件/etc/fdfs/storage-group2.conf,group3 的配置内容和 B 机器的保持一致。
$ sudo vim /etc/fdfs/storage-group2.conf
#需要修改的内容如下
group_name=group2
port=33000 # storage服务端口(默认23000,修改为33000)
base_path=/data/fastdfs/storage/group2 # 数据和日志文件存储根目录
store_path_count=6
store_path0=/data01/fastdfs # group2的第一个存储目录
store_path1=/data02/fastdfs # group2的第二个存储目录
store_path2=/data03/fastdfs # group2的第三个存储目录
store_path3=/data04/fastdfs # group2的第四个存储目录
store_path4=/data05/fastdfs # group2的第五个存储目录
store_path5=/data06/fastdfs # group2的第六个存储目录
tracker_server=10.58.10.136:22122 # tracker服务器IP和端口
tracker_server=10.58.10.137:22122 # tracker服务器IP和端口
tracker_server=10.58.10.138:22122 # tracker服务器IP和端口
http.server_port=8888 # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
  • client 的配置文件和 A 机器一致,此处不做重复。
  • 制作启动 group2 和 group3 的 service,上面已有,直接复制即可。
  • 执行启动脚本,直到fastdfs-storage-group2.servicefastdfs-storage-group3.service服务起来即可。

安装nginx和fastdfs的nginx模块

step1 在 fastdfs 的目录中,将 http.confmime.types 文件拷贝到 /etc/fdfs 目录下面,支持 nginx 访问 storage 服务。

# 在三台机器上都需要执行
$ cp ./conf/http.conf /etc/fdfs/ #供 nginx 访问使用
$ cp ./conf/mime.types /etc/fdfs/ #供 nginx 访问使用

step2 安装 fastdfs 的 nginx 模块:

# 在三台机器上都需要执行
$ tar -zxvf V1.20.tar.gz
$ cp fastdfs-nginx-module-1.20/src/mod_fastdfs.conf /etc/fdfs/mod_fastdfs.conf

step3 然后修改 fastdfs-nginx-module-1.20/src/config 文件,找到 ngx_module_incsCORE_INCS 两处,修改如下:

ngx_module_incs=”/usr/include/fastdfs /usr/include/fastcommon/”
CORE_INCS=”$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/”

如果不修改,在编译 nginx 的时候,会出这种错误:/usr/include/fastdfs/fdfs_define.h:15:27: fatal error: common_define.h: No such file or directory

step4 之后我们解压 nginx,安装 nginx 服务:

$ tar -zxvf nginx-1.12.2.tar.gz
$ cd nginx-1.12.2
$ ./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_auth_request_module --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' --add-module=${YOUR_PATH}/fastdfs-nginx-module-1.20/src
$ make
$ make install

注意,上面 ${YOUR_PATH} 改为 fastdfs-nginx-module-1.20 的父目录,保证路径正确。

  • 修改A机器 /etc/fdfs/mod_fastdfs.conf 配置文件:
connect_timeout=2
network_timeout=30
base_path=/data/fastdfs/ngx_mod
load_fdfs_parameters_from_tracker=true
storage_sync_file_max_delay = 86400
use_storage_id = false
storage_ids_filename = storage_ids.conf
tracker_server=10.58.10.136:22122 # tracker服务器IP和端口
tracker_server=10.58.10.137:22122 # tracker服务器IP和端口
tracker_server=10.58.10.138:22122 # tracker服务器IP和端口
group_name=group1/group2 # 全局
url_have_group_name = true
log_level=info
log_filename=
response_mode=proxy
if_alias_prefix=
flv_support = true
flv_extension = flv
group_count = 2
[group1]
group_name=group1 #group中
storage_server_port=23000
store_path_count=6
store_path0=/data01/fastdfs
store_path1=/data02/fastdfs
store_path2=/data03/fastdfs
store_path3=/data04/fastdfs
store_path4=/data05/fastdfs
store_path5=/data06/fastdfs
[group2]
group_name=group2
storage_server_port=33000
store_path_count=6
store_path0=/data07/fastdfs
store_path1=/data08/fastdfs
store_path2=/data09/fastdfs
store_path3=/data10/fastdfs
store_path4=/data11/fastdfs
store_path5=/data12/fastdfs
  • 配置 nginx 的配置文件,以便访问 storage
$ sudo vim /etc/nginx/nginx.conf
user nginx;
worker_prosesses on;
worker_rlimit_nofile 65535; error_log /var/log/nginx/error.log;
pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events {
worker_connections 65535;
use epoll;
accept_mutex off;
} http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
gzip on; server_names_bucket_hash_size 128;
client_header_buffer_size 32k;
larger_client_header_buffers 4 32k;
client_max_body_size 300m; proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connet_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 16k;
proxy_buffers 8 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k; proxy_cache_path /data/fastdfs/cache/nginx/proxy_cache levels=1:2
keys_zone=http-cache:200m max_size=1g inactive=30d;
proxy_temp_path /data/fastdfs/cache/nginx/proxy_cache/temp; include /etc/nginx/mime.types;
default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html; # Load configuration files for the default server block.
#include /etc/nginx/default.d/*.conf; location ~ ^/ok(\..*)?$ {
return 200 "OK";
} location /nginx {
stub_status on;
} location /healthcheck {
check_status on;
} location ^~ /group1/ {
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; add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header "Access-Control-Allow-Methods" "GET, POST, HEAD, PUT, DELETE, OPTIONS, PATCH";
add_header "Access-Control-Allow-Headers" "Origin, No-Cache, Authorization, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type";
if ($request_method = 'OPTIONS') {
return 200 'OK';
} proxy_pass http://fdfs_group1;
expire 30d;
}
location ^~ /group2/ {
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; add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header "Access-Control-Allow-Methods" "GET, POST, HEAD, PUT, DELETE, OPTIONS, PATCH";
add_header "Access-Control-Allow-Headers" "Origin, No-Cache, Authorization, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type";
if ($request_method = 'OPTIONS') {
return 200 'OK';
} proxy_pass http://fdfs_group2;
expire 30d;
}
location ^~ /group3/ {
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; add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header "Access-Control-Allow-Methods" "GET, POST, HEAD, PUT, DELETE, OPTIONS, PATCH";
add_header "Access-Control-Allow-Headers" "Origin, No-Cache, Authorization, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type";
if ($request_method = 'OPTIONS') {
return 200 'OK';
} proxy_pass http://fdfs_group3;
expire 30d;
} location ~/purge(/.*) {
allow 127.0.0.1;
allow 192.168.1.0/24;
allow 10.58.1.0/24;
deny all;
proxy_cache_purge http-cache $1$is_args$args;
}
} server {
listen 8888;
server_name localhost; location /ok.htm {
return 200 "OK";
} location ~/group[0-9]/ {
ngx_fastdfs_module;
} error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
} upstream fdfs_group1 {
server 10.58.10.136:8888 max_fails=0;
server 10.58.10.137:8888 max_fails=0; keepalive 10240;
check interval=2000 rise=2 fall=3 timeout=1000 type=http default_down=false;
check_http_send "GET /ok.htm HTTP/1.0\r\nConnection:keep-alive\r\n\r\n";
check_keepalive_requests 100;
} upstream fdfs_group2 {
server 10.58.10.136:8888 max_fails=0;
server 10.58.10.138:8888 max_fails=0; keepalive 10240;
check interval=2000 rise=2 fall=3 timeout=1000 type=http default_down=false;
check_http_send "GET /ok.htm HTTP/1.0\r\nConnection:keep-alive\r\n\r\n";
check_keepalive_requests 100;
} upstream fdfs_group3 {
server 10.58.10.137:8888 max_fails=0;
server 10.58.10.138:8888 max_fails=0; keepalive 10240;
check interval=2000 rise=2 fall=3 timeout=1000 type=http default_down=false;
check_http_send "GET /ok.htm HTTP/1.0\r\nConnection:keep-alive\r\n\r\n";
check_keepalive_requests 100;
} }
  • 启动 nginx 服务:
sudo nginx -c /etc/nginx/nginx.conf

访问http://localhost/ok.htm看看是否返回 200 的状态,并有 OK 内容。如果启动失败,可以查看nginx的日志,日志在/var/log/nginx/error.log文件中,这个也是 nginx 在 Centos 中的默认错误日志路径,如果修改过 error_log,那么在 error_log 指定的文件中查看错误信息。

  • B 和 C 机器的配置基本一样,nginx 的配置文件完全一样,唯一需要修改的是/etc/fdfs/mod_fastdfs.conf,在 group_name 中根据节点中 storage 的配置修改对应的名字即可。但是需要注意的是方括号[groupX]中X一定是顺序递增的,从1开始。

问题总结

遇到问题,第一,我们通过 Console 打印的信息排查服务启动失败的原因;第二,通过日志排查。大多数时候,日志是最有效的排查方式,没有之一。tracker 或 storage 服务的日志存放在其服务对应配置文件中 base_path 配置项指定路径的 logs 目录下面。 nginx的日志,如果开启了自己指定日志路径,那么就是自己指定的路径下查找。如果默认,在 Centos 下面大多数在 /var/log/nginx/ 目录下面。当然,在这种环境中我们排查的不单单是 nginx,还有 fastdfs 的对 nginx 的扩展模块,这时候,要考虑 fastdfs-nginx-module 的日志的排查,其日志存放路径为 /etc/fdfs/mod_fastdfs.conf 配置中 base_path 指定的路径。

集群中多个 group 配置端口

每个 group 都需要独立一个 storage 服务,因此同一台主机上 storage group 的端口不能冲突,这里我把 group1 的规划为 23000,group2 的规划为 33000,group3 的规划为43000.

相同名称的 group 不能在同一台机器上,因为 tracker 调度时,相同名称的 group 之间会自动进行同步,需要相同的端口号。故此,两台主机上统一名称的 group 必须保证 storage 的端口一致。

集群中多个group存储路径的配置

同一主机不同的 group 存储路径不要放在一起,需要分开配置。

不同主机相同的 group 存储路径可以不一致,但是数量必须保证相同,大小也应该基本一致。

同一节点多个 storage 的配置

在同一个机器上,我们部署了两个 group,三台机器组成的集群,每个 group 在另外一个节点中保存一份副本。使用命令systemctl start fastdfs-storage-groupx.service启动的时候,另外一个 group 无法启动(groupx 为 group1、group2、group3)。一直显示为 Loaded: loaded (/usr/lib/systemd/system/fastdfs-storage-group1.service; enabled; vender preset: disabled),直到最好失败 Active: inactive 变为 Active: exited (下图为tracker的,storage 的问题类似)。

![](https://img2018.cnblogs.com/blog/1844824/201910/1844824-20191024163722170-1129664866.png)

图3 storage_group无法启动

当时的解决方法:每个 storage 启动时都需要 systemctl daemon-reload 一下,然后启动即可。

假如要启动A机器中的 fastdfs-storage-group1.servicefastdfs-storage-group2.service,则需要执行如下操作:

  • 先启动 fastdfs-storage-group1.service
sudo systemctl daemon-reload
sudo systemctl enable fastdfs-storage-group1.service
sudo systemctl start fastdfs-storage-group1.service
  • 观察 fastdfs-storage-group1.service 的状态:
systemctl status fastdfs-storage-group1.service
  • 当看到 active 为 running 的时候,说明启动成功了,然后启动 fastdfs-storage-group2.service;否则没启动成功,查看日志寻找问题即可:
sudo systemctl daemon-reload
sudo systemctl enable fastdfs-storage-group2.service
sudo systemctl start fastdfs-storage-group3.service
  • 观察 fastdfs-storage-group2.service 的状态,直到起来为止。

可能会出现 Unkown lvalue 'ExecRestart' in section 'Service' 的警告日志,目前未找到解决方法,当时执行了 yum install systemd-* 的命令,也没能解决这个问题(有知道解决方案的朋友麻烦告知一下)。

fastdfs的nginx模块配置

在所有 storage 机器上,修改 /etc/fdfs/mod_fastdfs.conf 时,根据不同的 storage 中的 group 修改 group_name 中的值,但是需要注意两个配置项目,下面就 group2 和 group3 为例说明一下:

  • 全局的 group_name

全局配置中的 group_name 必须用”/“分割,值为局部中的 group_name 的值。比如:

group_name=group2/group3。
  • group 中的 group_name

    group 标识一定是从 group1 开始,依次为 group2,这里的标识就是方括号中的字符串,类似 mysql 配置文件中的 [Mysql]。
group_name=group2/group3  # 全局
...
group_count = 2
[group1] # 一定要注意这个地方
group_name=grou2 #group中
storage_server_port=33000
store_path_count=6
......
[group2] # 还有这个地方,都是有序的
group_name=group3
storage_server_port=43000
store_path_count=6
......

最后,个人理解,错误在所难免,欢迎各位朋友批评指正,如有不对的地方,烦请指出。后续我就 FastDFS 的 Tracker 和 Storage 之间的关系做一个详细的解释。


该文首发《虚怀若谷》个人博客,转载前请务必署名,转载请标明出处。

古之善为道者,微妙玄通,深不可识。夫唯不可识,故强为之容:

豫兮若冬涉川,犹兮若畏四邻,俨兮其若客,涣兮若冰之释,敦兮其若朴,旷兮其若谷,混兮其若浊。

孰能浊以静之徐清?孰能安以动之徐生?

保此道不欲盈。夫唯不盈,故能敝而新成。

请关注我的微信公众号:下雨就像弹钢琴,Thanks♪(・ω・)ノ

分布式FastDFS集群部署的更多相关文章

  1. FastDFS集群部署

    之前介绍过关于FastDFS单机部署,详见博文:FastDFS+Nginx(单点部署)事例 下面来玩下FastDFS集群部署,实现高可用(HA) 服务器规划: 跟踪服务器1[主机](Tracker S ...

  2. FastDFS集群部署(转载 写的比较好)

    FastDFS集群部署   之前介绍过关于FastDFS单机部署,详见博文:FastDFS+Nginx(单点部署)事例 下面来玩下FastDFS集群部署,实现高可用(HA) 服务器规划: 跟踪服务器1 ...

  3. Fastdfs集群部署以及基本操作

    FastDFS引言 本地存储与分布式文件系统 本地存储的缺点: 是否有备份? 没有 成本角度? 贵 ​ 服务器 :用于计算 ---- cpu/内存 ​ 用于存储 ---- 硬盘大 存储瓶颈? 容量有限 ...

  4. Linux安装fastdfs集群部署

    过程问题: make: gcc:命令未找到 解决: yum -y install gcc 一.环境和版本: Linux环境:CentOS 7.6 libfastcommon版本:1.0.39 Fast ...

  5. 分布式文件系统FastDFS集群部署

    1.源码开放下载地址:https://github.com/happyfish100 早期源码开放下载地址:https://sourceforge.net/projects/fastdfs/files ...

  6. MinIO分布式集群部署方式

    文章转载自:https://blog.51cto.com/u_10950710/4843738 关于分布式集群MinIo 单机Minio服务存在单点故障,如果是一个有N块硬盘的分布式Minio,只要有 ...

  7. fastdfs集群安装过程_学习笔记

    最终效果 初始化为6个节点 在/usr/local/software 目录下上传需要用到tar包,分别在各个节点上传 使用scp 将本地software目录复制到其他节点上 73.74为 tracke ...

  8. 关于Linux单机、集群部署FastDFS分布式文件系统的步骤。

    集群部署:2台tarcker服务器,2台storage服务器. 192.168.201.86   ---------(trackerd+storage+nginx) 192.168.201.87   ...

  9. FastDfs集群docker化部署

    初识分布式文件系统FastDFS- 1.分布式与集群的区别 区别:集群是个物理形态,分布式是个工作方式.只要是一堆机器,就可以叫集群,他们是不是一起协作着干活,这个谁也不知道:一个程序或系统,只要运行 ...

随机推荐

  1. 【学习笔记】第六章 python核心技术与实践--深入浅出字符串

    [第五章]思考题答案,仅供参考: 思考题1:第一种方法更快,原因就是{}不需要去调用相关的函数: 思考题2:用列表作为key在这里是不被允许的,因为列表是一个动态变化的数据结构,字典当中的key要求是 ...

  2. CSS——字体

    1.字体样式font-family.颜色color <!DOCTYPE html> <html> <head> <meta charset="UTF ...

  3. 同步FIFO design and IP level verification

    一.前言 应聘IC前端相关岗位时,FIFO是最常考也是最基本的题目.FIFO经常用于数据缓存.位宽转换.异步时钟域处理.随着芯片规模的快速增长,灵活的system verilog成为设计/验证人员的基 ...

  4. 深入理解JVM内存分配策略

    理解JVM内存分配策略 三大原则+担保机制 JVM分配内存机制有三大原则和担保机制 具体如下所示: 优先分配到eden区 大对象,直接进入到老年代 长期存活的对象分配到老年代 空间分配担保 对象优先在 ...

  5. 【带着canvas去流浪(14)】Three.js中凹浮雕模型的生成方式

    目录 一. 方案1:ThreeBSP.js或ThreeCSG.js扩展库 二. 方案2:平面镂空模型拉伸 三. 方案3:Cinema 4D建模后输出模型文件 示例代码托管在:http://www.gi ...

  6. java数据结构——递归(Recursion)例题持续更新中

    继续学习数据结构递归,什么是递归呢?字面理解就是先递出去,然后回归,递归核心思想就是直接或间接调用本身,好比从前有座山,山里有位老和尚,在给小和尚讲故事,讲的是从前有座山,山里有位老和尚,在给小和尚讲 ...

  7. Axure实现banner功能

    1.添加一个动态面板,添加上一张.下一张及当前banner对应的序号圆圈,如图所示: 当添加好元素后,实现自动轮播:点击[轮播图面板]页面:选中动态面板:右边添加事件编辑栏——属性——载入时——添加动 ...

  8. Flask基础(07)-->正则自定义转换器

    正则自定义转换器 为什么要自定义正则转换器? 因为默认转换器太过于笨重,往往不能满足我们实际业务的需求,这时候我们就需要自定义正则转换器了. 那么我们怎么自定义正则转换器呢? from flask i ...

  9. Golang:线程 和 协程 的区别

    作者:林冠宏 / 指尖下的幽灵 博客:http://www.cnblogs.com/linguanh/ GitHub : https://github.com/af913337456/ 掘金:http ...

  10. Salesforce学习之路-developer篇(三)利用Visualforce Page实现页面的动态刷新案例学习

    Visualforce是一个Web开发框架,允许开发人员构建可以在Lightning平台上本地托管的自定义用户界面.其框架包含:前端的界面设计,使用的类似于HTML的标记语言:以及后端的控制器,使用类 ...