1、准备工作

1.1、准备基础环境

先准备三个虚拟机来模拟集群,它们的ip分别是192.168.36.132、192.168.36.133、192.168.36.134,宿主系统都是centos7,并且都安装了带有阿里云镜像加速的Docker。

1.2、准备FDFS+NGINX部署文件

FDFS并没有在docker hub上维护官方镜像,所以需要自行构建。用于创建镜像的部署文件可以通过以下链接获取

链接:https://pan.baidu.com/s/1LXSELSMvBb_QDruQBs44ow 
提取码:pcb5

文件结构应如下图所示

docker部署sftp写入权限 docker部署fastdfs集群_分布式

或者使用以下命令直接拉取已经创建好的镜像如下:

docker pull registry.cn-shenzhen.aliyuncs.com/sgeoc/fastdfs:v1.0

使用该方法的可跳过构建FDFS镜像的小节。

创建镜像的部署文件列表(src文件下的文件)如下:

名称

说明

fdfs

fdfs源文件

libfastcommon

fdfs的公用函数包

fastdfs-nginx-module

nginx与fdfs的关联模块,编译nginx时使用

nginx

对外提供文件访问能力

1.3、准备NGINX镜像

此NGINX(称为:nginx_master)镜像与1.2的NGINX(称为:nginx_worker)不同。nginx_worker用于对外提供单节点的文件访问能力,而nginx_master用于对多个nginx_worker作负载均衡。NGINX官方镜像可用以下命令获取

docker pull nginx

1.4 、架构设计

docker部署sftp写入权限 docker部署fastdfs集群_git_02

由上图可以看出,每个节点都有Tracker,Storage,和nginx_worker。Tracker是FDFS中的进程,负责获取文件系统的状态,是监控者,一个节点只有一个Tracker进程。Storage也是FDFS的进程,在集群中是真正用于存储和管理文件的角色,理论上一个节点可以有多个Storage进程,这要视乎group的设置和分布情况(每个节点有多少个group,就有多少个Storage进程)。为了缩减文章篇幅,上图中Tracker只会部署单节点,部署多节点Tracker时只需要在tracker.conf中部署多个tracker_server便可。文件存储路径也只会使用/home/dfs,并且只有一个group,名称是group1,所以每个节点只有一个Storage进程。最终相关文件的节点,和分配如下表所示:

名称

IP地址

服务和文件

端口

Centos 1

192.168.32.132

tracker

22122

192.168.32.132

storage-group1

23000

192.168.32.132

libfastcommon

-

192.168.32.132

nginx_worker

8888

192.168.32.132

fastdfs-nginx-module

-

192.168.32.132

nginx_master

8081

Centos 2

192.168.32.133

storage-group1

23000

192.168.32.133

libfastcommon

-

192.168.32.133

nginx_worker

8888

192.168.32.133

fastdfs-nginx-module

-

Centos 3

192.168.32.134

storage-group1

23000

192.168.32.134

libfastcommon

-

192.168.32.134

nginx_worker

8888

192.168.32.134

fastdfs-nginx-module

-

2、构建FDFS

部署FDFS时需要关注的配置文件在<path to file>/FDFS/src/fastdfs/docker/dockerfile_network/conf目录下,讲述它们的作用不是本文的内容,所以这里不予以赘述。需要说明的一个文件是容器的启动脚本<path to file>FDFS/src/fastdfs/docker/dockerfile_network/fastdfs.sh,里面的代码如下:

#!/bin/bash

new_val=$FASTDFS_IPADDR
old="com.ikingtech.ch116221"

sed -i "s/$old/$new_val/g" /etc/fdfs/client.conf
sed -i "s/$old/$new_val/g" /etc/fdfs/storage.conf
sed -i "s/$old/$new_val/g" /etc/fdfs/mod_fastdfs.conf

cat  /etc/fdfs/client.conf > /etc/fdfs/client.txt
cat  /etc/fdfs/storage.conf >  /etc/fdfs/storage.txt
cat  /etc/fdfs/mod_fastdfs.conf > /etc/fdfs/mod_fastdfs.txt

mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.t
cp /etc/fdfs/nginx.conf /usr/local/nginx/conf

echo "start trackerd"
/etc/init.d/fdfs_trackerd start

echo "start storage"
/etc/init.d/fdfs_storaged start

echo "start nginx"
/usr/local/nginx/sbin/nginx 

tail -f  /dev/null

这些代码负责修改单个节点下的配置文件里的配置,再启动tracker,storage,和nginx_worker。此外还有nginx的配置文件nginx.conf,其代码有一关键部分如下:

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_worker和fdfs结合在了一起,使得fdfs中的文件能够对外访问。

2.1、使用Dockerfile构建镜像

下载的文件中应该有两个Dockerfile文件(Dockerfile_git和Dockerfile_src),Dockerfile_git使用git上的部署文件部署,而Dockerfile_src使用src里面的文件部署,理论上两个都可以。使用docker build命令即可完成镜像构建,Dockerfile_src中的代码如下:

FROM alpine:3.10

LABEL "maintainer
RUN mkdir -p /usr/local/src

COPY src /usr/local/src

RUN set -x \
  && chmod -R 777 /usr/local/src \
  && echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories \
  && echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
  && apk update \
  && apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev \
  && cd /usr/local/src \
  && tar -xf nginx-1.15.4.tar.gz \
  && cd /usr/local/src/libfastcommon \
  && ./make.sh \
  && ./make.sh install \
  && cd /usr/local/src/fastdfs/ \
  && ./make.sh \
  && ./make.sh install \
  && cd /usr/local/src/nginx-1.15.4/ \
  && ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ \
  && make && make install \
  && apk del .build-deps \
  && apk add --no-cache pcre-dev bash \
  && mkdir -p /home/dfs \
  && mv /usr/local/src/fastdfs/docker/dockerfile_network/fastdfs.sh /home \
  && mv /usr/local/src/fastdfs/docker/dockerfile_network/conf/* /etc/fdfs \
  && chmod +x /home/fastdfs.sh \
  && rm -rf /usr/local/src*

VOLUME /home/dfs
EXPOSE 22122 23000 8888 8080 80
CMD ["/home/fastdfs.sh"]

Dockerfile_git中的代码如下:

FROM alpine:3.10

RUN set -x \
    && echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories \
    && echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
    && apk update \
    && apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev git \
    && mkdir -p /usr/local/src \
    && cd /usr/local/src \
    && git clone https://github.com/happyfish100/libfastcommon.git --depth 1 \
    && git clone https://github.com/happyfish100/fastdfs.git --depth 1    \
    && git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1  \
    && wget http://nginx.org/download/nginx-1.15.4.tar.gz \
    && tar -xf nginx-1.15.4.tar.gz \
    && cd /usr/local/src/libfastcommon \
    && ./make.sh \
    && ./make.sh install \
    && cd /usr/local/src/fastdfs/ \
    && ./make.sh \
    && ./make.sh install \
    && cd /usr/local/src/nginx-1.15.4/ \
    && ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ \
    && make && make install \
    && apk del .build-deps \
    && apk add --no-cache pcre-dev bash \
    && mkdir -p /home/dfs  \
    && mv /usr/local/src/fastdfs/docker/dockerfile_network/fastdfs.sh /home \
    && mv /usr/local/src/fastdfs/docker/dockerfile_network/conf/* /etc/fdfs \
    && chmod +x /home/fastdfs.sh \
    && rm -rf /usr/local/src*
VOLUME /home/dfs
EXPOSE 22122 23000 8888 8080
CMD ["/home/fastdfs.sh"]

3、Docker集群部署FDFS+nginx_worker和nginx_master

3.1 部署FDFS+nginx_worker

部署分布式存储集群和高可用负载均衡访问需要两个docker-compose文件,首先是基于FDFS+nginx_worker的镜像部署的docker-compose.yml,在Centos 1,Centos 2,Centos 3上运行docker-compose up -d命令。文件代码如下。

version: "3.1"
services:
  sgeocfdfs_1:
    image: sgeocfdfs:v1.0
    container_name: sgeocfdfs_1
    ports:
      - "22122:22122"
      - "23000:23000"
      - "8888:8888"
      - "80:80"

    environment:
      FASTDFS_IPADDR: 192.168.36.132

    volumes:
      - "/home/sword/Desktop/DS/fdfs_data:/home/dfs"

    network_mode: "host"

需要注意的是,FDFS的网络一定要使用host,或者nat,与宿主系统共享ip和端口,使用bridge的storage进程的ip会转为docker的虚拟ip。另外FASTDFS_IPADDR配置的tracker的ip。

3.2 部署nginx_master

nginx_master是数据访问的入口,所以它只需要在一台机器上部署便可,使用以下docker-compose.yml代码部署。

version: "3.1"
services:
  sgeoc_fdfs_nginx:
    image: nginx
    container_name: sgeoc_fdfs_nginx
    ports:
     - 8081:80
    volumes:
     - "/home/sword/Desktop/DS/nginx_data:/usr/share/nginx/html"
     - "/home/sword/Desktop/DS/NGINX/conf/nginx.conf:/etc/nginx/nginx.conf"

并且nginx.conf的配置如下

user  nginx;
worker_processes  10;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    include       /etc/nginx/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  /var/log/nginx/access.log  main;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;

        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
             root   /usr/share/nginx/html;
        }


        location ^~ /group1/{
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            proxy_pass http://fdfs_group1;

        }

    }

    upstream fdfs_group1 {
        server 192.168.36.132:8888 max_fails=0;
        server 192.168.36.133:8888 max_fails=0;
        server 192.168.36.134:8888 max_fails=0;
        keepalive 10240;

    }
}

需要说明的是,upstream部分对应3台机器的nginx_worker,对nginx_master进行访问的链接只要符合^~ /group1/表达式的都会转发到fdfs_group1中做负载

3、Python代码示例

from fdfs_client.client import Fdfs_client, get_tracker_conf
tracker_path = get_tracker_conf('E:/PycharmProject/sgeoc_fdfs_client/client.conf')
client = Fdfs_client(tracker_path)
ret = client.upload_by_filename('E:/PycharmProject/sgeoc_fdfs_client/1.png')

其中client.conf文件对应FDFS中的/etc/fdfs/client.conf文件