FastDFS Distributed File Storage

Posted by Josh18657 on Tue, 24 Dec 2019 01:31:55 +0100

What is FastDFS?

FastDFS is an open source, lightweight, distributed file system.He solves issues such as large data storage and load balancing.Especially suitable for online services with small and medium files (4KB < FileSize < 500MB), such as video, audio, picture websites, etc.
FastDFS is an open source and lightweight distributed file system. It is implemented by pure C and supports UNIX system classes such as Linux and FreeBSD. It is not a universal file system, but can only be accessed through a proprietary API. At present, it provides C, Java and PHP API s tailored for Internet applications to solve large file storage problems, and the pursuit of high performance and scalability FastDFS can be regarded as text-based.A key value pair storage system for a piece, called a distributed file storage service, is more appropriate.

Features of FastDFS?

  • Files are not stored in blocks, and the uploaded files correspond to the files in the OS file system
  • Save only one file that supports the same content, saving disk space (only one storage is set in a group)
  • Download files support the HTTP protocol and can be used with built-in Web Servers or with other Web Servers
  • Support online expansion
  • Supports master-slave files
  • Storage server can save file attributes (meta-data)V2.0 network communication uses libevent, supports military access, overall better performance

FastDFS architecture

Tracker Server Tracking Server

Track the server, mainly for dispatching and load balancing.Recording in memory the status information of all storage groups and storage servers that exist in the cluster is the hub for interaction between the client and the data server.Compared to master in GlastFS, Master is more streamlined, does not record file index information, and takes up less memory.
Tracker is the coordinator of FastDFS and manages all storgae server s and groups. Each story connects to the tracker after it is started, informs the tarcker of its own grouping, etc., and maintains a periodic heartbeat. Tracker builds a mapping table for the group --> storage server list based on the story's heartbeat.

Tracker has very little meta-information to manage and stores it all in memory.Additionally, meta-information on tracker is generated from information reported by storage and does not need to persist any data. This makes tracker very easy to expand. By adding tracker machines directly, tracker clusters can be extended to serve tracker clusters, where each tracker is completely equivalent, and all trackers accept the heartbeat information from storage.Generate metadata information to provide read and write services.

Storage server storage server

A storage server, also known as a storage node or data server, has file and file properties (meta-data) stored on it.Storage server calls management files directly from the OS's file system.

Strage is organized as a group. A group contains multiple stroage machines. Data is backed up from each other. Storage space is based on the smallest storage volume of the group. Therefore, it is recommended that the storage capacity within the same group be the same to prevent waste of resources.

Organizational storage in groups facilitates application isolation, is responsible for balance, and defines the number of copies (the number of storages within a group is the number of copies of that group).For example, to isolate resources by writing data from different services into different groups, we can also write data from one service into multiple groups for load balancing.

The capacity of a group is limited by the storage capacity of a single machine, and when there is storag corruption within the group, data recovery can only depend on other storage machines in the group, making recovery time very long.

storage within a group depends on the local file system for each story, which can be configured with multiple data store directories.

When storage accepts a write file operation, it chooses one of the storage directories to store the files according to the configured rules.To avoid too many files in a single directory, a level 2 subdirectory, 256 directories at each level, totaling 65536 directories, is created in each data store directory when the store is first started. Newly written files are routed to one of these subdirectories by hash, and then the file data is stored directly as a local file in the directory.

client server client

Clients, as originators of business requests, use the TCP/IP protocol to interact with tracking servers or storage nodes through proprietary interfaces.

group

Groups, also known as volumes., the files on the servers in the same group are identical, the storage servers in the same group are equal, file upload, deletion and other operations can be done on any one storage server, how many groups can be on one storage server, and how many groups can be on each storage server for a device.

Metadata file related properties

Key Value Pair methods, such as width=1024,heigth=768

FastDFS DDL Operation

Upload mechanism

First the client requests the Tracker service to get the IP address and port of the storage server corresponding to the group group to be operated on. Then the client requests to upload the file according to the returned IP address and port number. The storage server receives the request and produces the file. The file content is written to disk and returned to the client file_id, path information, file name, etc. The client saves the phase.Close information upload completed.

FastDFS memory storage mechanism:
1, select tracker server
When there is more than one tracker server in the cluster, since tracker servers are fully peer-to-peer, clients can choose any tracker when uploading files.When tracker receives a request for upload file, it is assigned a group to store the file, which supports the following rules for selecting a group:

  • Round Robin, poll all group s
  • Specified Group specifies a certain group
  • Load Balance, group with more storage remaining takes precedence

2, select storage server
When a group is selected, tracker will select a storage server within the group to give to the client, supporting the following rules for selecting a storage

  • Round Robin polls all storage s within the group
  • First server ordered by ip sorted by IP
  • First server ordred by priority is sorted by priority, which is configured on the store

3, select storage path
When the storage server is assigned, the client sends a write file request to the storage, and the storage will assign a data storage directory to the file, supporting the following rules:

  • Round Robin Multiple Storage Directory Polling
  • Priority of Maximum Remaining Storage Space

4, Generate FileID
When the directory is selected, Storage generates a FileID for the file, spliced by storage server ip +file creation time +file size +file crc32 +random number.The binary string is then base64 encoded and converted to a printable string.When two levels of directory are selected as the storage directory, storage assigns a fileid to the files. Each storage directory has two levels of 256*256 subdirectories. Storage hash es twice by file fileid, routes to one of the subdirectories, and stores the files in that subdirectory with fileid as the file name.

5, Generate file name
When a file is stored in a subdirectory, it is considered to be stored successfully. A file name is generated for the file, which is stitched together by group, storage directory, two-level subdirectory, fileid, file suffix name (specified by the client, mainly used to distinguish file types).

6, storage writes to disk
After each story writes a file, it also writes a binlog, which does not contain file data and values contain meta-information such as file names. This binlog is used for background synchronization. storage records the progress of synchronization to other storages within the Group so that it can continue synchronizing after restart, and the progress is recorded with a timestamp.

7. Report regularly to tracker
storage synchronization progress is reported on all trackers as part of the metadata, and trackers use this as a reference when selecting storages (see download mechanism below)

Storage generates a file name that contains the source storage ID/IP address and the file creation timestamp.Storage periodically reports file synchronization to tracker, including file timestamps to other storages in the same group.After the tracker receives the file synchronization report from Storage, it finds the minimum timestamp that each Storage in the group synchronizes to and stores it in memory as a storage property.

Download mechanism

The client requests the Tracker service with the file name information to get the IP and Port of the storage server, and then the client requests the download of the file with the returned IP address and port number. The storage server returns the file to the client after it has not received the request.

As with Upload file, clients can choose any tracker server when downloading files.Tracker sends a download request to a trakcer. It must bring the file name information with it. Tracker parses the group, size, creation time of the file from the file name, and then chooses a storage for the request to serve the read request.Since files within a group are synchronized asynchronously in the background, it is possible that they may appear while reading and have not yet been synchronized to some storage server s. To try to avoid accessing such storage, tracker chooses the readable storage within a group according to the following rules:

  • 1, the source storage of the file upload (identified by inverting the storage ID/IP from the file name)
  • 2, (Current Time - File Creation Timestamp) >File Synchronization Delay Threshold (e.g. one day)
  • 3, the file creation timestamp < the timestamp to which the story was synchronized.(If the current storage synchronizes to a timestamp of 10 and the file creation timestamp of 8, the file has been synchronized)
  • 4, File Creation Timestamp== the time stamp to which the storage is synchronized, and (Current Time - File Creation Timestamp) > Maximum time to synchronize a file (for example, 5 minutes).

The file synchronization delay threshold above and the maximum time to synchronize a file are two parameters that are configured in tracker.conf with storage_sync_file_max_delay and storage_sync_file_max_time, respectively.
FastDFS uses time stamps to solve file access problems caused by file synchronization delays.The time of servers within the cluster needs to be consistent, with a time error of no more than 1S, so NTP time servers are recommended to ensure consistent time.

FastDFS File Synchronization Mechanism

We've been talking about file synchronization above, but what's the real synchronization mechanism for files?
FastDFS synchronous files are copied asynchronously by binlog.stroage server records file upload, deletion and other operations using binlog (metadata of record file) files, and synchronizes files according to binlog.Here are a few examples of binlog file contents:
Path to binlog file $base_path/data/sync/binlog. *

1574850031 C M00/4C/2D/rBCo3V3eTe-AP6SRAABk7o3hUY4681.wav
1574850630 C M00/4C/2D/rBCo3V3eUEaAPMwRAABnbqEmTEs918.wav
1574851230 C M00/4C/2D/rBCo3V3eUp6ARGlEAABhzomSJJo079.wav
1574851230 C M00/4C/2D/rBCo3V3eUp6ABSZWAABoDiunCqc737.wav
1574851830 C M00/4C/2D/rBCo3V3eVPaAYKlIAABormd65Ds168.wav
1574851830 C M00/4C/2D/rBCo3V3eVPaAPs-CAABljrrCwyI452.wav
1574851830 C M00/4C/2D/rBCo3V3eVPaAdSeKAABrLhlwnkU907.wav
1574852429 C M00/4C/2D/rBCo3V3eV02Ab4yKAABmLjpCyas766.wav
1574852429 C M00/4C/2D/rBCo3V3eV02AASzFAABorpw6oJw030.wav
1574852429 C M00/4C/2D/rBCo3V3eV02AHSM7AAB0jpYtHQA019.wav

As you can see above, the binlog file has three columns, which are the timestamp, the type of operation, and the file ID (without the group name)

The file operation type uses a single letter encoding, where the source operation is capitalized and the synchronized operation is the corresponding shoe letter
C: upload files
D: Delete the file (delete)
A: Append the file (append)
M: Partial file update
U: set metadata
T: truncate the file
L: Create symbolic links (file de-duplication, save only one copy of the same content)

Storage servers within the same group are peer-to-peer, and file upload, deletion, and other operations can be performed on any one of the storage servers.File synchronization only occurs between storage servers within a group, using the push method, where the source server synchronizes to other storage servers in the group.For other storage servers in the same group, one storage server starts a thread for file synchronization.

File synchronization is incremental, recording the synchronized locations into a mark file.The mark file store path is $base_path/data/sync/.Example mark file contents:

binlog_index=3
binlog_offset=382
need_sync_old=1
sync_old_done=1
until_timestamp=1571976211
scan_row_count=2033425
sync_row_count=2033417

With binlog's asynchronous replication, there must be synchronization delays, such as mysql's master-slave data synchronization.

data recovery

Single disk data recovery

When a storage disk in our Group is damaged and we want to replace it, the data is automatically recovered when the disk is replaced.
How to determine if a single disk data recovery is required: detect the existence of two subdirectories 00/00 and FF/FF (default 256 for each level of subdirectories) in the $Store_path/data directory, and if one does not exist, automatically create the required subdirectories and start the automatic recovery of single disk data.
Single disk data recovery logic:

  • 1. Obtain an available storage server from the tracker server as the source server;
  • 2, pull the binlog of the storage path (store_path sequence corresponding) from the storage server and store it locally
  • 3, more local binlog s copy files from the source storage server to the corresponding directory under $store_path/data/
  • 4. The service can not be provided until the recovery of single disk data is completed.

Docker Install FastDFS

Pre-startup analysis

We're using the season/fastdfs:1.2 mirror here, so we'll take his dockerfile and see how it works

cat > Obtain_dockerfile.sh <<-'EOF'
#!/bin/bash
#DOC This is a docker file obtained from docker images to see how to start
export PATH=$PATH
if [ $# -eq 1 ];then
        docker history --format {{.CreatedBy}} --no-trunc=true $1 |sed "s/\/bin\/sh\ -c\ \#(nop)\ //g"|sed "s/\/bin\/sh\ -c/RUN/g" | tac
    else
        echo "sh Obtain_dockerfile.sh $DOCKER_IMAGE"
fi
EOF

The dockerfile obtained by executing the script is as follows

# sh Obtain_dockerfile.sh season/fastdfs:1.2
ADD file:b908886c97e2b96665b7afc54ff53ebaef1c62896cf83a1199e59fceff1dafb5 in /
CMD ["/bin/bash"]
MAINTAINER season summer summer@season
RUN apt-get update && apt-get install -y gcc gcc-multilib libc6-dev-i386 make nano htop --no-install-recommends
RUN rm -rf /var/lib/apt/lists/*
COPY dir:9bb2976272b997f08c6435eb1f63b3801cec525f269b6a1de45ef02ba72dc919 in /FastDFS_v4.08
COPY dir:a74a73cd25b708ddc7dc6556b6f9608066876c344de608fb0f2e14dda04a48ba in /libevent-2.0.14
COPY dir:d5fde946a90870a8850d6e9b0b8b7be4e5e41c0b0f2d18cc19589e6caa56061e in /zlib-1.2.8
COPY dir:46967139f210ec8160e07010de80fea21e3950bf7cc680ccd10f3d01d458afce in /fastdfs-nginx-module
COPY dir:d39817fa72b763e78b1fe17483b6fcbebe769e79caf0a2411a9b35b5b104c5f7 in /nginx-1.8.0
COPY file:232f9aba296194eae5e61a56594f2d9b7fc4f03bfb7739e423335b36c7866653 in /entrypoint.sh
WORKDIR /libevent-2.0.14
RUN ./configure --prefix=/usr/local/libevent-2.0.14 && make && make install  && make clean
RUN echo '/usr/local/libevent-2.0.14/include' >> /etc/ld.so.conf
RUN echo '/usr/local/libevent-2.0.14/lib' >> /etc/ld.so.conf
RUN ldconfig
WORKDIR /FastDFS_v4.08
RUN ./make.sh C_INCLUDE_PATH=/usr/local/libevent-2.0.14/include LIBRARY_PATH=/usr/local/libevent-2.0.14/lib && ./make.sh install && ./make.sh clean
WORKDIR /nginx-1.8.0
RUN ./configure --user=root --group=root --prefix=/etc/nginx --with-http_stub_status_module --with-zlib=/zlib-1.2.8 --without-http_rewrite_module --add-module=/fastdfs-nginx-module/src
RUN make
RUN make install
RUN make clean
RUN ln -sf /etc/nginx/sbin/nginx /sbin/nginx
RUN mkdir /fastdfs
RUN mkdir /fastdfs/tracker
RUN mkdir /fastdfs/store_path
RUN mkdir /fastdfs/client
RUN mkdir /fastdfs/storage
RUN mkdir /fdfs_conf
RUN cp /FastDFS_v4.08/conf/* /fdfs_conf
RUN cp /fastdfs-nginx-module/src/mod_fastdfs.conf /fdfs_conf
WORKDIR /
RUN chmod a+x /entrypoint.sh
ENTRYPOINT &{["/entrypoint.sh"]}

You can see that our startup was done by executing this script. Now let's look at the following in this script:

#!/bin/bash
#set -e

TRACKER_BASE_PATH="/fastdfs/tracker"
TRACKER_LOG_FILE="$TRACKER_BASE_PATH/logs/trackerd.log"

STORAGE_BASE_PATH="/fastdfs/storage"
STORAGE_LOG_FILE="$STORAGE_BASE_PATH/logs/storaged.log"

TRACKER_CONF_FILE="/etc/fdfs/tracker.conf"
STORAGE_CONF_FILE="/etc/fdfs/storage.conf"

NGINX_ACCESS_LOG_FILE="/etc/nginx/logs/access.log"
NGINX_ERROR_LOG_FILE="/etc/nginx/logs/error.log"

MOD_FASTDFS_CONF_FILE="/etc/fdfs/mod_fastdfs.conf"

# remove log files
if [  -f "/fastdfs/tracker/logs/trackerd.log" ]; then
    rm -rf "$TRACKER_LOG_FILE"
fi

if [  -f "/fastdfs/storage/logs/storaged.log" ]; then
    rm -rf "$STORAGE_LOG_FILE"
fi

if [  -f "$NGINX_ACCESS_LOG_FILE" ]; then
    rm -rf "$NGINX_ACCESS_LOG_FILE"
fi

if [  -f "$NGINX_ERROR_LOG_FILE" ]; then
    rm -rf "$NGINX_ERROR_LOG_FILE"
fi

if [ "$1" = 'shell' ]; then
    /bin/bash
fi

if [ "$1" = 'tracker' ]; then
    echo "start  fdfs_trackerd..."

    if [ ! -d "/fastdfs/tracker/logs" ]; then
        mkdir "/fastdfs/tracker/logs"
    fi

    n=0
    array=()
    #Loop Read Profile
    while read line
    do
        array[$n]="${line}";
        ((n++));
    done < /fdfs_conf/tracker.conf

    rm "$TRACKER_CONF_FILE"
    #${!Array[@]} is the subscript of the array
    for i in "${!array[@]}"; do
        #Determine if group name is empty
        if [ ${STORE_GROUP} ]; then
            #If it is not empty, determine if the field storage_group is included and replace the line
            [[ "${array[$i]}" =~ "store_group=" ]] && array[$i]="store_group=${STORE_GROUP}"
        fi
        # Circular Append Configuration
        echo "${array[$i]}" >> "$TRACKER_CONF_FILE"
    done

    touch  "$TRACKER_LOG_FILE"
    ln -sf /dev/stdout "$TRACKER_LOG_FILE"

    fdfs_trackerd $TRACKER_CONF_FILE
    sleep 3s  #delay wait for pid file
    # tail -F --pid=`cat /fastdfs/tracker/data/fdfs_trackerd.pid`  /fastdfs/tracker/logs/trackerd.log
    # wait `cat /fastdfs/tracker/data/fdfs_trackerd.pid`
    tail -F --pid=`cat /fastdfs/tracker/data/fdfs_trackerd.pid`  /dev/null
 fi

if [ "$1" = 'storage' ]; then
    echo "start  fdfs_storgaed..."
    n=0
    array=()

    while read line
    do
        array[$n]="${line}";
        ((n++));
    done < /fdfs_conf/storage.conf

    rm "$STORAGE_CONF_FILE"

    for i in "${!array[@]}"; do
        if [ ${GROUP_NAME} ]; then
            [[ "${array[$i]}" =~ "group_name=" ]] && array[$i]="group_name=${GROUP_NAME}"
        fi

        if [ ${TRACKER_SERVER} ]; then
                [[ "${array[$i]}" =~ "tracker_server=" ]] && array[$i]="tracker_server=${TRACKER_SERVER}"
        fi
        echo "${array[$i]}" >> "$STORAGE_CONF_FILE"
    done

    if [ ! -d "/fastdfs/storage/logs" ]; then
        mkdir "/fastdfs/storage/logs"
    fi

    touch  "$STORAGE_LOG_FILE"
    ln -sf /dev/stdout "$STORAGE_LOG_FILE"

    fdfs_storaged "$STORAGE_CONF_FILE"
    sleep 3s  #delay wait for pid file
    # tail -F --pid=`cat /fastdfs/storage/data/fdfs_storaged.pid`  /fastdfs/storage/logs/storaged.log
    #wait -n `cat /fastdfs/storage/data/fdfs_storaged.pid`
    tail -F --pid=`cat /fastdfs/storage/data/fdfs_storaged.pid`  /dev/null
fi

if [ "$1" = 'nginx' ]; then
    echo "starting nginx..."
    # ln log files to stdout/stderr
    touch  "$NGINX_ACCESS_LOG_FILE"
    ln -sf /dev/stdout "$NGINX_ACCESS_LOG_FILE"
    touch  "$NGINX_ERROR_LOG_FILE"
    ln -sf /dev/stderr "$NGINX_ERROR_LOG_FILE"

    # change mod_fastfdfs.conf
    n=0
    array=()

    while read line
    do
        array[$n]="${line}";
        ((n++));
    done < /fdfs_conf/mod_fastdfs.conf

    if [  -f "$MOD_FASTDFS_CONF_FILE" ]; then
        rm -rf "$MOD_FASTDFS_CONF_FILE"
    fi

    for i in "${!array[@]}"; do
        if [ ${GROUP_NAME} ]; then
            [[ "${array[$i]}" =~ "group_name=" ]] && array[$i]="group_name=${GROUP_NAME}"
        fi

        if [ ${TRACKER_SERVER} ]; then
                [[ "${array[$i]}" =~ "tracker_server=" ]] && array[$i]="tracker_server=${TRACKER_SERVER}"
        fi

        if [ ${URL_HAVE_GROUP_NAME} ]; then
                [[ "${array[$i]}" =~ "url_have_group_name=" ]] && array[$i]="url_have_group_name=${URL_HAVE_GROUP_NAME}"
        fi

        if [ ${STORAGE_SERVER_PORT} ]; then
                [[ "${array[$i]}" =~ "storage_server_port=" ]] && array[$i]="storage_server_port=${STORAGE_SERVER_PORT}"
        fi

        echo "${array[$i]}" >> "$MOD_FASTDFS_CONF_FILE"
    done

    nginx -g "daemon off;"

We simply analyzed the script and found that it judged whether to start trakcer, storage or nginx according to the parameters passed after startup. We also looked at what the script is like to start the test now.

Start tracker

docker run -ti -d --name trakcer \
    -v /etc/localtime:/etc/localtime
    -v /tracker_data:/fastdfs/tracker/data \
    --net=host \
    --restart=always \
    season/fastdfs tracker

tracker listens on 2222122 after startup, and we can also change the port by passing environment variables

-e port=22222

Configurations in all profiles can be passed in as environment variables

#Environment variables and defaults that tracker can pass
disabled=false
bind_addr=
port=22122
connect_timeout=30
network_timeout=60
base_path=/fastdfs/tracker
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
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
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

Start storage

docker run -di --name storage \
     --restart=always \
     -v /storage_data:/fastdfs/storage/data \
     -v /store_path:/fastdfs/store_path \
     --net=host \
     -e TRACKER_SERVER=172.16.1.170:22122 season/fastdfs:1.2 storage

Transitive environment variables

disabled=false
group_name=group1
bind_addr=
client_bind=true
port=23000
connect_timeout=30
network_timeout=60
heart_beat_interval=30
stat_report_interval=60
base_path=/fastdfs/storage
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=/fastdfs/store_path
subdir_count_per_path=256
tracker_server=172.16.1.170:22122
log_level=info
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 = false
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
file_sync_skip_invalid_record=false
use_connection_pool = false
connection_pool_max_idle_time = 3600
http.domain_name=
http.server_port=8888

Test fastdfs

Enter the tracker container

docker exec -it tracker bash
grep 22122 /home/fdfs/client.conf
sed -i "s#`grep 22122 /home/fdfs/client.conf`#tracker_server=172.16.1.170:22122#g" /home/fdfs/client.conf

#Use the following command to view fastdfs cluster status
fdfs_monitor /etc/fdfs/client.conf
#Upload a file under test
fdfs_upload_file /etc/fdfs/client.conf /etc/hosts
    group1/M00/00/00/rBABql33W5CAK7yFAAAAnrLoM8Y9254622

#Download Files
root@test01:/etc/fdfs# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/rBABql33W5CAK7yFAAAAnrLoM8Y9254622
root@test01:/etc/fdfs# ls -l rBABql33W5CAK7yFAAAAnrLoM8Y9254622
-rw-r--r-- 1 root root 158 Dec 16 10:26 rBABql33W5CAK7yFAAAAnrLoM8Y9254622
root@test01:/etc/fdfs# cat rBABql33W5CAK7yFAAAAnrLoM8Y9254622
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

#Delete Files
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/rBABql33W5CAK7yFAAAAnrLoM8Y9254622

Start nginx for other programs to access and use

docker run -id --name fastdfs_nginx \
    --restart=always \
    -v /store_path:/fastdfs/store_path \
    -p 8888:80 \
    -e GROUP_NAME=group1 \
    -e TRACKER_SERVER=172.16.1.170:22122 \
    -e STORAGE_SERVER_PORT=23000 \
    season/fastdfs:1.2 nginx

Be careful:

```nginx.conf
server {
listen 8888;
server_name localhost;
location ~ /group([0-9])/M00 {
root //fastdfs/store_path/data;
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

Changeable Profile

```bash
grep -Ev "^#|^$" mod_fastdfs.conf
connect_timeout=2
network_timeout=30
base_path=/tmp
load_fdfs_parameters_from_tracker=true
storage_sync_file_max_delay = 86400
use_storage_id = false
storage_ids_filename = storage_ids.conf
tracker_server=tracker:22122
storage_server_port=23000
group_name=group1
url_have_group_name=true
store_path_count=1
#storage_path0 needs to be the same as storage
store_path0=/fastdfs/store_path
log_level=info
log_filename=
response_mode=proxy
if_alias_prefix=
flv_support = true
flv_extension = flv
group_count = 0

Cluster building

We just need to start storage and nginx on another machine and then do a load balancing for all

Topics: Linux Nginx Docker zlib Unix