FastDFS是用c语言编写的一款开源的分布式文件系统。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。由跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)组成。它主要解决的是海量数据存储的问题。
FastDFS架构包括 Tracker server和Storage server。客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载。
Tracker server作用是负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server提供文件上传服务。可以将tracker称为追踪服务器或调度服务器。
Storage server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage server没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。
FastDFS集群中的Tracker server可以有多台,Tracker server之间是相互平等关系同时提供服务,Tracker server不存在单点故障。客户端请求Tracker server采用轮询方式,如果请求的tracker无法提供服务则换另一个tracker。
Storage集群采用了分组存储方式。storage集群由一个或多个组构成,集群存储总容量为集群中所有组的存储容量之和。一个组由一台或多台存储服务器组成,组内的Storage server之间是平等关系,不同组的Storage server之间不会相互通信,同组内的Storage server之间会相互连接进行文件同步,从而保证同组内每个storage上的文件完全一致的。一个组的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是一致的。
采用分组存储方式的好处是灵活、可控性较强。比如上传文件时,可以由客户端直接指定上传到的组也可以由tracker进行调度选择。一个分组的存储服务器访问压力较大时,可以在该组增加存储服务器来扩充服务能力(纵向扩容)。当系统容量不足时,可以增加组来扩充存储容量(横向扩容)。
Storage server会连接集群中所有的Tracker server,定时向他们报告自己的状态,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。
客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。文件索引信息包括:组名,磁盘编号,数据两级目录,文件名。这里的文件名是由文件上传的源头服务器、文件上传的时间戳、文件大小、随机数经过base64加密后的一个串。
tracker根据请求的文件路径即文件ID 来快速定位文件。
比如请求下边的文件:
出于高可用的需求tracker和storage都使用两台服务器,storage使用两个组用以说明storage可以任意扩充组实现线性扩展。
client请求tracker进行文件上传、下载、删除。
client可以通过java client API方式进行文件上传、下载、删除。
client可以通过http方式进行文件下载。tracker通过nginx提供http下载接口。
client也可以直接访问storage进行文件上传、下载、删除,但建议client通过tracker进行文件上传、下载、删除。
每个tracker server互相平等,tracker server上部署nginx不是为了对外提供http文件下载接口,tracker上nginx只是起到负载均衡、反向代理的作用。tracker的nginx会反向代理转发至storage上的nginx。
每台storage上也部署nginx,storage上的nginx与tracker上的nginx有区别,storage上的nginx需要安装FastDSF-nginx模块,此模块的作用是使用FastDFS和nginx进行整合,nginx对外提供http文件下载接口,注意:nginx只提供文件下载接口不提供上传接口。文件上传仍然通过java client API进行。
https://github.com/happyfish100/fastdfs/wiki
安装fastdfs依赖包:
apt-get install build-essential -y # 安装编译工具
unzip libfastcommon-master.zip
cd libfastcommon-master
./make.sh
./make.sh install
安装 fastdfs:
unzip fastdfs-master.zip
cd fastdfs-master/
./make.sh
./make.sh install
配置跟踪服务器tracker:
mkdir /data/fastdfs/tracker -p
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
sed -i 's#base_path=/home/yuqing/fastdfs#base_path=/data/fastdfs/tracker#g' /etc/fdfs/tracker.conf
配置存储服务器storage:
mkdir /data/fastdfs/storage -p
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
sed -i 's#base_path=/home/yuqing/fastdfs#base_path=/data/fastdfs/storage#g' /etc/fdfs/storage.conf
sed -i 's#store_path0=/home/yuqing/fastdfs#store_path0=/data/fastdfs/storage#g' /etc/fdfs/storage.conf
sed -i 's#tracker_server=192.168.209.121:22122#tracker_server=172.17.2.234:22122#g' /etc/fdfs/storage.conf
/etc/init.d/fdfs_trackerd start
/etc/init.d/fdfs_storaged start
安装成功后可以通过/usr/bin/fdfs_test测试上传
在tracker机器上或者是storage机器上修改/etc/fdfs/client.conf配置文件
base_path=/data/fastdfs/tracker/
tracker_server=172.17.2.234:22122
测试上传:
root@unode01:~# fdfs_upload_file /etc/fdfs/client.conf 00.jpg
group1/M00/00/00/rBEC6l1JG0KALBhnAABOo6ovw3w035.jpg # 出现这样的文件id说明文件上传成功
目前还不能下载,因为fastDFS没有提供下载接口,需要使用nginx提供下载接口。Tracker和Storage都需要安装nginx。
1、为了做反向代理,请求tracker上的nginx服务,反向代理选择出对应的group组,再根据tracker接收的storage的同步信息情况,最终决定一台storage服务器。然后给客户端返回storage的ip和端口。
2、做tracker的负载均衡。
apt install build-essential -y
apt install libtool -y
apt install libpcre3 libpcre3-dev -y
apt install zlib1g-dev -y
apt-get install openssl libssl-dev -y
useradd nginx -M -s /usr/sbin/nologin
tar xf nginx-1.12.0.tar.gz
unzip fastdfs-nginx-module-master.zip
cd nginx-1.12.0/
./configure --prefix=/application/nginx-1.12.0 --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-threads --with-file-aio --with-http_stub_status_module --add-module=/root/tools/fastdfs-nginx-module-master/src
make
make isntall
cp fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
# 修改mod_fastdfs.conf配置文件的内容
connect_timeout=10
tracker_server=172.17.2.234:22122
url_have_group_name=true
store_path0=/data/fastdfs/storage
cp fastdfs-master/conf/http.conf /etc/fdfs/
cp fastdfs-master/conf/mime.types /etc/fdfs/
修改nginx安装目录下的conf下的nginx.conf配置文件
在server模块儿中修改:
server {
listen 8888;
server_name localhost;
location ~/group[0-9]/ {
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
配置完后启动nginx
以下配置作为拓展:
upstream storage_server_group1{
#192.168.188.22:80实际上是storage server上nginx的ip和端口,配置这个是为了做下载的反向代理,nginx提供了下载接口,所以这个是nginx的ip和端口
server 192.168.188.22:80 weight=10;
#这个80端口不是storage的port也不是http.server_port,而是storage上#nginx的服务端口,因为我们通过浏览器访问图片其实访问的是nginx提供的接口,其实访问的是nginx的服务
server 192.168.188.23:80 weight=10;
}
# 如果有group2的话还可以配置
upstream storage_server_group2{
server 192.168.101.7:80 weight=10;
server 192.168.101.8:80 weight=10;
}
在server模块儿中添加:
listen 80;
server_name localhost;
location /group1{
proxy_redirect off;
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_pass http://storage_server_group1; #做反向代理,访问tracker,将访问的资源反向代理到对应的storage对应的nginx上。
}
location /group2{
proxy_redirect off;
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_pass http://storage_server_group2;
}
这里访问地址:
http://IP地址/group1/M00/00/00/wKi8FlhEjAWAG92gAAIy5JEMGq8315.png
请求Tracker服务器下载图片,其实请求的是Tracker服务器上的nginx服务,因为nginx服务的端口是80端口,而tracker服务端口是22122。
tracker上的nginx起到http访问的反向代理作用,反向代理到group对应的所有storage上的nginx服务。客户端请求tracker上的nginx服务,根据配置的location /group1找到对应的group1下所有的storage服务器上的nginx服务的ip和端口(提供下载接口),然后由tracker决定使用哪台storage,最后将该storage的ngnix服务的ip和port返回给客户端。客户端拿到storage的nginx服务的ip和端口,去请求这个nginx服务,根据请求中的group1/M00与storage的nginx配置的进行匹配,然后获取到文件的存储目录,然后在根据两级目录和文件名来获取到文件。
location /group1/M00/{
root /home/FastDFS/fdfs_storage/data;
ngx_fastdfs_module;
}
为什么非得要用nginx呢,请求中不是已经指定group了吗,tracker就可以定位到对应的组了?
虽然tracker理论上是可以根据请求的group定位到对应的storage Server,但是却不能获取到storage上的nginx服务,因为nginx提供了下载接口。所以只能通过tracker上的nginx做http访问的反向代理,根据group 代理到group对应的storage上的nginx服务,然后根据tracker中同步的信息决定选择哪台,最后将storage上的nginx服务返给客户端。
linux系统下直接安装:
pip install fdfs_client-py-master.zip
pip install mutagen
pip install requests
windows安装步骤如下:
#from fdfs_client.sendfile import *
# 'ext_modules': [Extension('fdfs_client.sendfile',
# sources=['fdfs_client/sendfilemodule.c'])],
# 没有虚拟环境可直接安装
G:\pywwroot\fdfs_client-py-master>workon dailyfresh
(dailyfresh) G:\pywwroot\fdfs_client-py-master>python setup.py install
# 还需要安装以下两个包
(dailyfresh) G:\pywwroot\fdfs_client-py-master>pip install mutagen
(dailyfresh) G:\pywwroot\fdfs_client-py-master>pip install requests
# 注意修改client.conf配置文件中的IP地址
from fdfs_client.client import *
import time
client_file = 'client.conf'
test_file = '00.jpg'
download_file = 'test2.txt'
try:
client = Fdfs_client(client_file)
# upload
ret_upload = client.upload_by_filename(test_file)
print(ret_upload)
time.sleep(5) # 等待5s,否则下载时会报错文件不存在
file_id = ret_upload['Remote file_id'].replace('\\', '/') # 新版本文件存放Remote file_id格式变化
print(file_id)
# download
ret_download = client.download_to_file(download_file, file_id)
print(ret_download)
# delete
ret_delete = client.delete_file(file_id)
print(ret_delete)
except Exception as e:
print(e)
构建tracker容器(跟踪服务器,起到调度的作用)
docker run -d --network=host --restart always --name tracker -v /data/fastdfs/tracker:/var/fdfs delron/fastdfs tracker
构建storage容器(存储服务器,提供容量和备份服务)
docker run -d --network=host --restart always --name storage -e TRACKER_SERVER=172.17.2.130:22122 -v /data/fastdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage
启动成功后查看开放的端口:
root@seed:/data/fastdfs_docker# netstat -lnput|grep fdfs
tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 5228/fdfs_storaged
tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 5125/fdfs_trackerd
nginx端口为:
root@seed:/data/fastdfs_docker# netstat -lnput|grep nginx # docker中自带的nginx
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 5217/nginx
IP | Hostname | System | Role |
---|---|---|---|
172.17.2.235 | unode02.ginvip.com | ubuntu16.04 | 安装tracker1, storage1 |
172.17.2.236 | unode03.ginvip.com | ubuntu16.04 | 安装tracker2, storage2 |
说明:
若要扩展更多 的tracker and storage节点,也是类似的操作
以下安装步骤在unode02机器上执行,unode03上的安装步骤类似,只是把文件夹名改为:tracker2, storage2,启动的容器名为:tracker2, storage2。配置文件一样。
在unode02上启动tracker1容器
root@unode02:~/# mkdir /data/fastdfs/tracker1/{data,conf} -p
在conf目录新建tracker.conf配置文件:
root@unode02:/data/fastdfs/tracker1/conf# cat tracker.conf
disabled=false
bind_addr=
port=22122
connect_timeout=30
network_timeout=30
base_path=/data/fast_data
max_connections=256
accept_threads=1
work_threads=4
store_lookup=2
store_group=group1
store_server=0
store_path=0
download_server=0
reserved_storage_space = 10%
log_level=info
run_by_group=
run_by_user=
allow_hosts=*
sync_log_buff_interval = 10
check_active_interval = 120
thread_stack_size = 64KB
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 = 16MB
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 = 0
use_storage_id = false
storage_ids_filename = storage_ids.conf
id_type_in_filename = ip
store_slave_file_use_link = false
rotate_error_log = false
error_log_rotate_time=00:00
rotate_error_log_size = 0
log_file_keep_days = 0
use_connection_pool = false
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
启动docker:
root@unode02:~/docker/fastdfs# cat start_tracker_docker.sh
#!/bin/bash
docker run -d --name tracker1 --net=host --restart always \
-v /etc/localtime:/etc/localtime \
-v /data/fastdfs/tracker1/data:/data/fast_data/ \
-v /data/fastdfs/tracker1/conf/tracker.conf:/etc/fdfs/tracker.conf \
morunchang/fastdfs sh tracker.sh
查看docker日志是否启动正常:
root@unode02:~/docker/fastdfs# docker logs tracker1
root@unode02:~# mkdir /data/fastdfs/storage1/{data,conf} -p
在conf目录新建storage.conf配置文件:(注意修改下面的IP地址)
root@unode02:~# cat /data/fastdfs/storage1/conf/storage.conf
disabled=false
group_name=group1
bind_addr=
client_bind=true
port=23002
connect_timeout=30
network_timeout=30
heart_beat_interval=30
stat_report_interval=60
base_path=/data/fast_data
max_connections=256
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
store_path_count=1
store_path0=/data/fast_data
subdir_count_per_path=256
tracker_server=172.17.2.235:22122
tracker_server=172.17.2.236:22122
log_level=debug
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=10
sync_binlog_buff_interval=10
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 = true
rotate_access_log = false
access_log_rotate_time=00:00
rotate_error_log = false
error_log_rotate_time=00:00
rotate_access_log_size = 0
rotate_error_log_size = 0
log_file_keep_days = 0
file_sync_skip_invalid_record=false
use_connection_pool = false
connection_pool_max_idle_time = 3600
http.domain_name=
http.server_port=9101
在conf目录下新建nginx.conf配置文件
root@unode02:~# cat /data/fastdfs/storage1/conf/nginx.conf
worker_processes 1;
error_log /data/fast_data/logs/nginx-error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
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 /data/fast_data/logs/nginx-access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 9101;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location ~ /group1/M00 {
root /data/fast_data/data;
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
在conf目录新建mod_fastdfs.conf配置文件:(注意修改下面的IP地址)
root@unode02:~# cat /data/fastdfs/storage1/conf/mod_fastdfs.conf
connect_timeout=30
network_timeout=30
base_path=/data/fast_data
load_fdfs_parameters_from_tracker=true
storage_sync_file_max_delay = 86400
use_storage_id = false
storage_ids_filename = storage_ids.conf
tracker_server=172.17.2.235:22122
tracker_server=172.17.2.236:22122
storage_server_port=23002
group_name=group1
url_have_group_name = true
store_path_count=1
store_path0=/data/fast_data
log_level=info
log_filename=
response_mode=proxy
if_alias_prefix=
#include http.conf
flv_support = true
flv_extension = flv
group_count = 0
注意上面的 #include http.conf 配置项不能少,少了会报下面的错误,导致nginx无法启动
ERROR - file: ../common/fdfs_http_shared.c, line: 128, param "http.mime_types_filename" not exist or is empty
在conf目录创建storage.sh文件
root@unode02:/data/fastdfs/storage1/conf# cat storage.sh
#!/bin/sh
/data/fastdfs/storage/fdfs_storaged /etc/fdfs/storage.conf
/etc/nginx/sbin/nginx
tail -f /data/fast_data/logs/storaged.log
在conf目录创建client.conf配置文件
root@unode02:/data/fastdfs/storage1/conf# cat client.conf
# connect timeout in seconds
# default value is 30s
connect_timeout=30
# network timeout in seconds
# default value is 30s
network_timeout=30
# the base path to store log files
base_path=/data/fastdfs/test
# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address
tracker_server=172.17.2.235:22122
tracker_server=172.17.2.236:22122
#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info
# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false
# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600
# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false
# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false
# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf
#HTTP settings
http.tracker_server_port=80
#use "#include" directive to include HTTP other settiongs
##include http.conf
配置完成后确认storage1下的配置文件有:
root@unode02:/data/fastdfs/storage1/conf# ll
total 20
-rw-r--r-- 1 root root 1491 Feb 23 17:44 client.conf
-rw-r--r-- 1 root root 528 Feb 23 17:51 mod_fastdfs.conf
-rw-r--r-- 1 root root 946 Feb 23 16:35 nginx.conf
-rw-r--r-- 1 root root 1289 Feb 23 16:33 storage.conf
-rw-r--r-- 1 root root 133 Feb 23 16:38 storage.sh
启动docker容器
root@unode02:~/docker/fastdfs# cat start_storage_docker.sh
#!/bin/bash
docker run -d --name storage1 --net=host --restart always \
-v /etc/localtime:/etc/localtime \
-v /data/fastdfs/storage1/data:/data/fast_data/ \
-v /data/fastdfs/storage1/conf/storage.sh:/storage.sh \
-v /data/fastdfs/storage1/conf/storage.conf:/etc/fdfs/storage.conf \
-v /data/fastdfs/storage1/conf/nginx.conf:/etc/nginx/conf/nginx.conf \
-v /data/fastdfs/storage1/conf/mod_fastdfs.conf:/etc/fdfs/mod_fastdfs.conf \
-v /data/fastdfs/storage1/conf/client.conf:/data/fastdfs/conf/client.conf \
morunchang/fastdfs sh storage.sh
root@unode02:~/docker/fastdfs# docker exec -it storage1 fdfs_monitor /data/fastdfs/conf/client.conf
参数说明:
tracker_server_count:2 # 表示2个Tracker Server
tracker server is 172.17.2.235:22122 # 表示Leader Tracker
group count: 1 # 表示有1个group
group name = group1 # 组名称是group1
storage server count = 2 # 组内有2个storage
active server count = 2 # 活动的storage有2个
storage server port = 23002 # storage的端口
storage HTTP port = 9101 # storage的文件访问端口
store path count = 1 # storage只挂了一个存储目录
total_upload_count = 11 # 总共上传了多少个文件
total_upload_bytes = 691405 # 总共上传了多少字节
success_upload_bytes = 691405 # 成功上传了多少字节
total_download_count = 2 # 总共下载了多少文件(使用java客户端)
docker exec -it storage1 bash
cd /data/fastdfs/conf
fdfs_test client.conf upload anti-steal.jpg
文件上传成功后,会提示文件访问地址,同时会自动同步到storage2,因此也可以通过storage2的IP,访问文件。
由于storage1的http端口配置为9101,所以真正的访问地址是:
http://172.17.2.235:9101/group1/M00/00/00/rBEC615SQfGAWNwEAABdrZgsqUU803.jpg
storage2的访问地址是:
http://172.17.2.236:9101/group1/M00/00/00/rBEC615SQfGAWNwEAABdrZgsqUU803.jpg
wget http://172.17.2.235:9101/group1/M00/00/00/xowDSFyCEcyAVz4gAABdrZgsqUU908.jpg
wget http://172.17.2.236:9101/group1/M00/00/00/xowDSFyCEcyAVz4gAABdrZgsqUU908.jpg
能下载文件就表示fastdfs同步文件成功,也表示fastdfs安装配置成功。
进入storage的data目录,执行以下指令
cd /data/fastdfs/storage1/data/data/
ls -lR|grep "^-"|wc -l
或者进入data目录下的sync目录,执行以下指令
cat binlog.000 |wc -l
binlog.000保存了storage中所有文件名
下载地址:
链接:https://pan.baidu.com/s/1fQ3Mi-Z3Gc8gS5dN0P8pNw
提取码:qmxa