什么是FastDFS

百度百科:FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。
FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

FastDFS是由余庆所开发的开源、免费的分布式文件系统,GitHub项目地址请点这里,其基本架构图如下:

FastDFS仅提供源码包,必须从源码编译安装,且其提供了nginx插件,也必须与nginx源码一起编译安装nginx,安装过程较为繁复。为快速搭建简易的开发、测试环境,我采用docker方式将源码下载、编译、配置过程完全自动化,采用docker-compose来组织docker容器,并采用一台tracker+一台storage的最小系统架构,且部署在一个容器内,这样就以最小的系统代价、最快的速度搭建起fastdfs使用环境了。标题中的”一键”稍显夸张,但事实上下载GitHub项目文件到本地后,只需两三条命令即可搞定一个最简单的FastDFS环境搭建。

**关于docker及docker-compose的安装,请见《Ubuntu安装docker和docker-compose》。&&

创建Dockerfile
本DockerFile采用的软件版本:

fastdfs:5.11
libfastcommon:1.0.36
fastdfs-nginx-module: 最新版(截至2017/11/28,为1.20)
nginx: 1.12.2
各源码均为在线下载。

DockerFile内容如下:

# 使用超小的Linux镜像alpine
FROM alpine:3.6

MAINTAINER YoungCoding <bingdianfeishui@gmail.com>

ENV HOME /root

# 安装准备
RUN    apk update \
        && apk add --no-cache --virtual .build-deps bash gcc libc-dev make openssl-dev pcre-dev zlib-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev

# 下载fastdfs、libfastcommon、nginx插件的源码
RUN     cd /root \
        && curl -fSL https://github.com/happyfish100/libfastcommon/archive/V1.0.36.tar.gz -o fastcommon.tar.gz \
        && curl -fSL  https://codeload.github.com/happyfish100/fastdfs/tar.gz/V5.11 -o fastfs.tar.gz \
        && curl -fSL  https://github.com/happyfish100/fastdfs-nginx-module/archive/master.tar.gz -o nginx-module.tar.gz \
        && tar zxf fastcommon.tar.gz \
        && tar zxf fastfs.tar.gz \
        && tar zxf nginx-module.tar.gz

# 安装libfastcommon
RUN     cd ${HOME}/libfastcommon-1.0.36/ \
        && ./make.sh \
        && ./make.sh install

# 安装fastdfs v5.11
RUN     cd ${HOME}/fastdfs-5.11/ \
        && ./make.sh \
        && ./make.sh install

# 配置fastdfs: base_dir
RUN     cd /etc/fdfs/ \
        && cp storage.conf.sample storage.conf \
        && cp tracker.conf.sample tracker.conf \
        && cp client.conf.sample client.conf \
        && sed -i "s|/home/yuqing/fastdfs|/var/local/fdfs/tracker|g" /etc/fdfs/tracker.conf \
        && sed -i "s|/home/yuqing/fastdfs|/var/local/fdfs/storage|g" /etc/fdfs/storage.conf \
        && sed -i "s|/home/yuqing/fastdfs|/var/local/fdfs/storage|g" /etc/fdfs/client.conf 

# 获取nginx源码,与fastdfs插件一起编译
RUN     cd ${HOME} \
        && curl -fSL http://nginx.org/download/nginx-1.12.2.tar.gz -o nginx-1.12.2.tar.gz \
        && tar zxf nginx-1.12.2.tar.gz \
        && chmod u+x ${HOME}/fastdfs-nginx-module-master/src/config \
        && cd nginx-1.12.2 \
        && ./configure --add-module=${HOME}/fastdfs-nginx-module-master/src \
        && make && make install

# 设置nginx和fastdfs联合环境,并配置nginx
RUN     cp ${HOME}/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/ \
        && sed -i "s|^store_path0.*$|store_path0=/var/local/fdfs/storage|g" /etc/fdfs/mod_fastdfs.conf \
        && sed -i "s|^url_have_group_name =.*$|url_have_group_name = true|g" /etc/fdfs/mod_fastdfs.conf \
        && cd ${HOME}/fastdfs-5.11/conf/ \
        && cp http.conf mime.types anti-steal.jpg /etc/fdfs/ \
        && echo -e "\
events {\n\
    worker_connections  1024;\n\
}\n\
http {\n\
    include       mime.types;\n\
    default_type  application/octet-stream;\n\
    server {\n\
        listen 8888;\n\
        server_name localhost;\n\

        location ~ /group[0-9]/M00 {\n\
            ngx_fastdfs_module;\n\
        }\n\
    }\n\
}">/usr/local/nginx/conf/nginx.conf

# 清理文件
RUN rm -rf ${HOME}/*
RUN apk del .build-deps gcc libc-dev make openssl-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev
RUN apk add bash pcre-dev zlib-dev


# 配置启动脚本,在启动时中根据环境变量替换nginx端口、fastdfs端口
# 默认nginx端口
ENV WEB_PORT 8888
# 默认fastdfs端口
ENV FDFS_PORT 22122
# 创建启动脚本
RUN     echo -e "\
mkdir -p /var/local/fdfs/storage/data /var/local/fdfs/tracker; \n\
ln -s /var/local/fdfs/storage/data/ /var/local/fdfs/storage/data/M00; \n\n\
sed -i \"s/listen\ .*$/listen\ \$WEB_PORT;/g\" /usr/local/nginx/conf/nginx.conf; \n\
sed -i \"s/http.server_port=.*$/http.server_port=\$WEB_PORT/g\" /etc/fdfs/storage.conf; \n\n\
if [ \"\$IP\" = \"\" ]; then \n\
    IP=`ifconfig eth0 | grep inet | awk '{print \$2}'| awk -F: '{print \$2}'`; \n\
fi \n\
sed -i \"s/^tracker_server=.*$/tracker_server=\$IP:\$FDFS_PORT/g\" /etc/fdfs/client.conf; \n\
sed -i \"s/^tracker_server=.*$/tracker_server=\$IP:\$FDFS_PORT/g\" /etc/fdfs/storage.conf; \n\
sed -i \"s/^tracker_server=.*$/tracker_server=\$IP:\$FDFS_PORT/g\" /etc/fdfs/mod_fastdfs.conf; \n\n\
/etc/init.d/fdfs_trackerd start; \n\
/etc/init.d/fdfs_storaged start; \n\
/usr/local/nginx/sbin/nginx; \n\
tail -f /usr/local/nginx/logs/access.log \
">/start.sh \
&& chmod u+x /start.sh

# 暴露端口。改为采用host网络,不需要单独暴露端口
# EXPOSE 80 22122

ENTRYPOINT ["/bin/bash","/start.sh"]
docker-compose.yaml
在DockerFile所在目录创建docker-compose.yaml,内容如下:

version: '3.0'

services:
    fastdfs:
        build: .
        image: youngcoding/fastdfs:5.11
        # 该容器是否需要开机启动+自动重启。若需要,则取消注释。
        #restart: always
        container_name: fastdfs
        environment:
            # nginx服务端口
            - WEB_PORT=8888
            # docker所在主机的IP地址
            - IP=192.168.56.110
        volumes:
            # 将本地目录映射到docker容器内的fastdfs数据存储目录,将fastdfs文件存储到主机上,以免每次重建docker容器,之前存储的文件就丢失了。
            - ${HOME}/docker-data/fdfs:/var/local/fdfs
        # 使docker具有root权限以读写主机上的目录
        privileged: true
        # 网络模式为host,即直接使用主机的网络接口
        network_mode: "host"
准备
$ cd <保存Dockerfile文件的路径>
# 检查文件夹下各文件是否齐全
$ ls
docker-compose.yaml     Dockerfile      log.sh

# 确保本机供挂载的存储文件夹存在,如不存在,则创建。注意,此文件夹需与docker-compose.yaml中设置的volume挂载目录一致,可以自行更改到其他文件夹。
$ mkdir -p ${HOME}/docker-data/fdfs
启动
$ docker-compose up -d
# 因为要下载软件包和源码,并编译,所以过程比较漫长,期间可能会出现红字的warning,不必理会。若报错,请根据提示排查。
...
Successfully built 4baafa5d2e75
Successfully tagged youngcoding/fastdfs:5.11
WARNING: Image for service fastdfs was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating fastdfs ...
Creating fastdfs ... done

# 查看容器运行状态
$ docker ps
或 $ docker-compose ps
CONTAINER ID        IMAGE                       COMMAND                 CREATED             STATUS              PORTS               NAMES
2a294bc410bd        youngcoding/fastdfs:5.11    "/bin/bash /start.sh"   4 minutes ago       Up 4 minutes                            fastdfs
测试
# 进入docker容器内终端
$ docker exec -it fastdfs或ID的前几位 /bin/bash

# 在容器内部终端执行上传测试
bash-4.3$ echo "Hello FastDFS!">index.html
bash-4.3$ fdfs_test /etc/fdfs/client.conf upload index.html
This is FastDFS client test program v5.11
...
[2017-11-28 14:05:25] DEBUG - base_path=/var/local/fdfs/storage, connect_timeout=30, network_timeout=60, tracker_server_count=1, 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
tracker_query_storage_store_list_without_group:
        server 1. group_name=, ip_addr=192.168.56.110, port=23000
group_name=group1, ip_addr=192.168.56.110, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71.html
source ip address: 192.168.56.110
file timestamp=2017-11-28 14:05:25
file size=15
file crc32=3529255
example file url: http://192.168.56.110/group1/M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71.html

# 下载测试
bash-4.3$ fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71.html
...
storage=192.168.56.110:23000
download file success, file size=15, file save to wKg4blodbSWAImI9AAAADwA12ic71.html

# 外部http访问测试
# 在主机或其他同局域网内机器上用浏览器访问上面的url。注意:若nginx的端口设置不为80,则需加上端口号
http://192.168.56.110:8888/group1/M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71.html
# 网页显示:Hello FastDFS!

# 删除测试
bash-4.3$ fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71.html
storage=192.168.56.110:23000
delete file success

# 退出容器终端
bash-4.3$ exit
管理容器
# 停止容器
$ docker stop <容器NAMES,也可以为容器ID的前几位>
或 $ docker-compose stop

# 更改compose或Dockerfile后重新生成并运行
$ docker-compose stop
$ docker-compose build
$ docker-compose up -d
或 $ docker-compose up -d --build #本条命令可代替上述三条命令

# 删除容器
$ docker rm <容器NAMES,也可以为容器ID的前几位>
或 $ docker-compose rm
查看日志

为避免每次需要查看日志都要执行 docker exec -it <fdfs ID> /usr/bin/tail -f <log_file> 命令,我将常见的查看日志命令封装到一个脚本中,每次只需要执行脚本就能查看不同服务的日志了。

新建日志监控脚本log.sh
新建log.sh,用来快速查看日志。内容如下:

#!/bin/bash
STORAGE=/var/local/fdfs/storage/logs/storaged.log
TRACKER=/var/local/fdfs/tracker/logs/trackerd.log
NGINX=/usr/local/nginx/logs/access.log

ID=`docker ps|grep fastdfs|awk '{print $1}'`
echo fastdfs.ID:$ID
echo 'Use param tracker|storage|nginx to see log of each service such as "./log.sh tracker". No param equals to "storage".'
CAT=$1
LOG=""
if [[ "${CAT}" = "tracker" ]];then
    LOG=${TRACKER}
elif [[ "${CAT}" = "nginx" ]]; then
    LOG=${NGINX}
else 
    LOG=${STORAGE}
fi

docker exec -it $ID /usr/bin/tail -f ${LOG}
给log.sh添加执行权限
$ chmod u+x log.sh
查看日志
$ ./log.sh tracker或storage或nginx

# 查看nginx日志,可以看到刚刚从外部http方式访问fastdfs文件的日志
$ ./log.sh nginx
192.168.56.100 - - [28/Nov/2017:14:10:33 +0000] "GET /group1/M00/00/00/wKg4blodbSWAImI9AAAADwA12ic71_big.html HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36"
至此,fastDFS简易测试环境搭建完毕,开发搞起来!!完。

 

可能的报错:

/usr/include/fastdfs/fdfs_define.h:15:27: fatal error: common_define.h: No such file or directory

解决方案:修改fastdfs-nginx-module-1.20/src/config文件,然后重新第7步开始
ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/"
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐