分布式FastDFS集群部署

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 节点。

高可用FasfDFS结构图

图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。

集群部署

准备环境

<center>表1 软件列表及版本</center>

名称 说明 链接
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会根据上面的文本信息重命名。

<center> 表2 服务器IP、服务分配、端口规划表 </center>

名称 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 的问题类似)。

当时的解决方法:每个 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♪(・ω・)ノ

微信二维码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容