FastDFS分布式文件存儲(chǔ)

FastDFS 分布式文件存儲(chǔ)

什么是FastDFS?

FastDFS是一個(gè)開源的輕量級的分布式文件系統(tǒng)。他解決了大量數(shù)據(jù)存儲(chǔ)和負(fù)載均衡等問題。特別適合以中小文件(4KB < FileSize < 500MB)為載體的在線服務(wù),如視頻,音頻,圖片網(wǎng)站等等。
FastDFS是一款開源的輕量級分布式文件系統(tǒng),他是由純 C 實(shí)現(xiàn),支持Linux,F(xiàn)reeBSD等UNIX系統(tǒng)類,不是通用的文件系統(tǒng),只能通過專有的API訪問,目前提供了C、Java和PHP API為互聯(lián)網(wǎng)應(yīng)用量身定做,解決大容量文件存儲(chǔ)問題,追求高性能和高擴(kuò)展性FastDFS可以看做是基于文件的key value pair存儲(chǔ)系統(tǒng),稱作分布式文件存儲(chǔ)服務(wù)更為合適。

創(chuàng)新互聯(lián)公司專注于蔚縣網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供蔚縣營銷型網(wǎng)站建設(shè),蔚縣網(wǎng)站制作、蔚縣網(wǎng)頁設(shè)計(jì)、蔚縣網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造蔚縣網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供蔚縣網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

FastDFS的特性?

  • 文件不分塊存儲(chǔ),上傳的文件和OS文件系統(tǒng)中的文件一一對應(yīng)
  • 支持相同內(nèi)容的文件只保存一份,節(jié)約磁盤空間(一個(gè)group里面只設(shè)置一個(gè)storage)
  • 下載文件支持HTTP協(xié)議,可以使用內(nèi)置的Web Server,也可以和其他的Web Server配合使用
  • 支持在線擴(kuò)容
  • 支持主從文件
  • 存儲(chǔ)服務(wù)器上可以保存文件屬性(meta-data)V2.0網(wǎng)絡(luò)通信采用libevent,支持發(fā)兵法訪問,整體性能更好

FastDFS架構(gòu)

FastDFS 分布式文件存儲(chǔ)

Tracker Server 跟蹤服務(wù)器

跟蹤服務(wù)器,主要做調(diào)度工作,起負(fù)載均衡的作用。在內(nèi)存中記錄集群中所存在的所有存儲(chǔ)組和存儲(chǔ)服務(wù)器的狀態(tài)信息,是客戶端和數(shù)據(jù)服務(wù)器交互的樞紐。相比GlastFS中的master 更為精簡,不記錄文件索引悉信息,占用的內(nèi)存量很少。
Tracker 是FastDFS的協(xié)調(diào)者,負(fù)責(zé)管理所有的 storgae server 和 Group,每個(gè)storage在啟動(dòng)后會(huì)連接tracker,并告知tarcker自己所屬的group等信息,并保持周期性的心跳,tracker根據(jù)storage的心跳悉信息,建立group --> storage server list 的映射表。

Tracker 需要管理的元信息很少,會(huì)全部存儲(chǔ)在內(nèi)存中。另外tracker上的元信息都是由storage匯報(bào)的信息生成的,本身不需要持久任何數(shù)據(jù),這樣使得tracker非常容易擴(kuò)展,直接增加tracker機(jī)器即可擴(kuò)展為tracker cluster 來服務(wù),cluster里每個(gè)tracker之間是完全對等的,所有的 tracker都接受storage的心跳信息。生成元數(shù)據(jù)信息來提供讀寫服務(wù)。

Storage server 存儲(chǔ)服務(wù)器

存儲(chǔ)服務(wù)器,又稱為存儲(chǔ)節(jié)點(diǎn)或者數(shù)據(jù)服務(wù)器,文件和文件屬性(meta-data)都保存在存儲(chǔ)服務(wù)器上。storage server直接利用OS的文件系統(tǒng)調(diào)用管理文件。

stroage 以組(group)為單位組織,一個(gè)group內(nèi)包含多臺stroage機(jī)器,數(shù)據(jù)互為備份,存儲(chǔ)空間以group內(nèi)容量最小的storage為準(zhǔn),所以建議同一個(gè)group 里面的storage容量是相同的,防止資源浪費(fèi)。

以group為單位組織存儲(chǔ)能方便的進(jìn)行應(yīng)用隔離,負(fù)責(zé)均衡,副本數(shù)定義(group內(nèi)storage的數(shù)量即為該group的副本數(shù))。比如將不同服務(wù)的數(shù)據(jù)寫到不同的group里面,來做到資源隔離,我們也可以把一個(gè)服務(wù)的數(shù)據(jù)寫到多個(gè)group里面來做負(fù)載均衡。

group的容量受單機(jī)存儲(chǔ)容量的限制,同時(shí)當(dāng)group內(nèi)有storag損壞,數(shù)據(jù)恢復(fù)只能依賴于group中其他storage機(jī)器,使得恢復(fù)時(shí)間會(huì)很長。

group內(nèi)每個(gè)storage的存儲(chǔ)依賴于本地文件系統(tǒng),storage可配置多個(gè)數(shù)據(jù)存儲(chǔ)目錄。

storage接受到寫文件操作時(shí),會(huì)根據(jù)配置好的規(guī)則,選擇其中一個(gè)存儲(chǔ)目錄來存儲(chǔ)文件。為了避免單個(gè)目錄下的文件數(shù)太多,在storage第一次啟動(dòng)時(shí),會(huì)在每個(gè)數(shù)據(jù)存儲(chǔ)目錄里創(chuàng)建2級子目錄,每級256個(gè),一共65536個(gè)目錄,新寫的文件會(huì)以hash的方式被路由到其中某個(gè)子目錄下,然后將文件數(shù)據(jù)直接作為一個(gè)本地文件存儲(chǔ)到該目錄中。

client server 客戶端

客戶端作為業(yè)務(wù)請求的發(fā)起方,通過專有接口,使用TCP/IP協(xié)議與跟蹤服務(wù)器或存儲(chǔ)節(jié)點(diǎn)發(fā)生數(shù)據(jù)交互。

group 組

組,又可稱為卷。,同組內(nèi)服務(wù)器上的文件是完全相同的,同一組內(nèi)的storage server 之間是對等的,文件上傳,刪除等操作可以在任意一臺storage server 上進(jìn)行,一個(gè)storage server上上面可以對應(yīng)著多少組,每個(gè)組在storage server上可以對應(yīng)一個(gè)設(shè)備。

meta data 文件相關(guān)屬性

鍵值對( Key Value Pair) 方式,如:width=1024,heigth=768

FastDFS DDL操作

上傳機(jī)制

首先客戶端請求Tracker服務(wù)獲取到要操作的group組對應(yīng)的存儲(chǔ)服務(wù)器的ip地址和端口,然后客戶端根據(jù)返回的IP地址和端口號請求上傳文件,存儲(chǔ)服務(wù)器接收到請求后生產(chǎn)文件,并且將文件內(nèi)容寫入磁盤并返回給客戶端file_id、路徑信息、文件名等信息,客戶端保存相關(guān)信息上傳完畢。
FastDFS 分布式文件存儲(chǔ)
FastDFS內(nèi)存存儲(chǔ)機(jī)制:
1,選擇tracker server
當(dāng)集群中不止一個(gè)tracker server時(shí),由于tracker server之間是完全對等的關(guān)系,客戶端在upload文件時(shí)可以任意選擇一個(gè)tracker。當(dāng)tracker接收到upload file的請求時(shí),會(huì)為該文件分配一個(gè)可以存儲(chǔ)該文件的group,支持如下選擇group的規(guī)則:

  • Round Robin,輪詢所有的group
  • Specified Group 指定某一個(gè)確定的group
  • Load Balance,剩余存儲(chǔ)空間多的group 優(yōu)先

2,選擇storage server
當(dāng)選定group后,tracker會(huì)在group內(nèi)選擇一個(gè)storage server 給客戶端,支持如下選擇storage的規(guī)則

  • Round Robin 在group內(nèi)的所有storage輪詢
  • First server ordered by ip 按照IP排序
  • First server ordred by priority 按照優(yōu)先級排序,優(yōu)先級在storage上配置

3,選擇storage path
當(dāng)分配好storage server后,客戶端將向storage發(fā)送寫文件請求,storage將會(huì)為文件分配一個(gè)數(shù)據(jù)存儲(chǔ)目錄,支持如下規(guī)則:

  • Round Robin 多個(gè)存儲(chǔ)目錄輪詢
  • 剩余存儲(chǔ)空間最多的優(yōu)先

4,生成FileID
選定目錄之后,storage會(huì)為文件生成一個(gè)FileID,由storage server ip + 文件創(chuàng)建時(shí)間 + 文件大小 + 文件crc32 +隨機(jī)數(shù)拼接。然后將這個(gè)二進(jìn)制串進(jìn)行base64編碼,轉(zhuǎn)換為可打印的字符串。選擇兩級目錄 當(dāng)選定存儲(chǔ)目錄之后,storage會(huì)為文件分配一個(gè)fileid,每個(gè)存儲(chǔ)目錄下有兩級256*256的子目錄,storage會(huì)按文件fileid進(jìn)行兩次hash(猜測),路由到其中一個(gè)子目錄,然后將文件以fileid為文件名存儲(chǔ)到該子目錄下。

5,生成文件名
當(dāng)文件存儲(chǔ)到某個(gè)子目錄后,即認(rèn)為該文件存儲(chǔ)成功,接下來會(huì)為該文件生成一個(gè)文件名,文件名由group、存儲(chǔ)目錄、兩級子目錄、fileid、文件后綴名(由客戶端指定,主要用于區(qū)分文件類型)拼接而成。

6,storage寫入磁盤
每個(gè)storage寫文件后,同時(shí)會(huì)寫一份binlogbinlog里面不包含文件數(shù)據(jù),值包含文件名等元信息,這份binlog用于后臺同步,storage會(huì)記錄向Group內(nèi)其他storage同步的進(jìn)度,以便重啟后能接上上次的進(jìn)度繼續(xù)同步;進(jìn)度以時(shí)間戳的方式進(jìn)行記錄。

7,定期向tracker匯報(bào)信息
storage同步進(jìn)度會(huì)作為元數(shù)據(jù)的一部分會(huì)報(bào)道所有的tracker上,tracker在選擇storage的時(shí)候會(huì)以此作參考(看下面下載機(jī)制)

storage生成的文件名中,包含源頭storage ID/IP地址和文件創(chuàng)建時(shí)間戳。storage 定時(shí)向tracker報(bào)告文件同步情況,包括向同組內(nèi)其他storage同步到的文件時(shí)間戳。tracker 收到storage的文件同步報(bào)告后,找出該組內(nèi)每臺storage唄同步到的最小時(shí)間戳,作為storage屬性保存到內(nèi)存中。

下載機(jī)制

客戶端帶上文件名信息請求Tracker服務(wù)獲取到storage服務(wù)器的IP和Port,然后client更具返回的IP地址和端口號請求下載文件,存儲(chǔ)服務(wù)器沒收到請求后返回文件給客戶端。

跟Upload file 一樣,在下載文件時(shí)客戶端可以選擇任意的tracker server。tracker發(fā)送下載請求給某個(gè)trakcer,必須帶上文件名信息,tracker從文件名中解析出文件的group、大小、創(chuàng)建時(shí)間等信息,然后為該請求選擇一個(gè)storage用來服務(wù)讀取請求。由于group內(nèi)的文件同步時(shí)在后臺異步進(jìn)行的,所以有可能出現(xiàn)在讀的時(shí)候,文件還沒有同步到某些storage server上,為了盡量避免訪問到這樣的storage,tracker按照如下規(guī)則選擇group內(nèi)可讀的storage:

  • 1,該文件上傳的源頭storage(通過文件名反解出storage ID/IP來判別)
  • 2,(當(dāng)前時(shí)間-文件創(chuàng)建時(shí)間戳) > 文件同步延遲閥值(如一天)
  • 3,文件創(chuàng)建時(shí)間戳 < storage被同步到的時(shí)間戳。(如果當(dāng)前storage同步到的時(shí)間戳為10,文件創(chuàng)建時(shí)間戳為8,說明這個(gè)文件已經(jīng)被同步)
  • 4,文件創(chuàng)建時(shí)間戳 == storage 被同步到的時(shí)間戳,且(當(dāng)前時(shí)間-文件創(chuàng)建時(shí)間戳) > 同步一個(gè)文件的最大時(shí)常(如5分鐘)。

上述文件同步延遲閥值和同步一個(gè)文件的最大時(shí)長這兩個(gè)參數(shù),在tracker.conf中配置,配置項(xiàng)分別是 storage_sync_file_max_delay 和 storage_sync_file_max_time。
因?yàn)镕astDFS利用時(shí)間戳來解決文件同步延遲帶來的文件訪問問題。集群內(nèi)部服務(wù)器的時(shí)間需要保持一致,要求時(shí)間誤差不超過1S,所以建議使用NTP時(shí)間服務(wù)器來確保時(shí)間一致。

FastDFS 文件同步機(jī)制

我們上面一直在說文件同步,但是文件真正的同步機(jī)制又是什么樣子的呢?
FastDFS同步文件采用binlog異步復(fù)制方式。stroage server 使用binlog(記錄文件的元數(shù)據(jù))文件記錄文件上傳、刪除等操作,根據(jù)binlog進(jìn)行文件同步。下面 給出幾行binlog文件內(nèi)容實(shí)例:
binlog文件的路徑$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

從上面可以看出,binlog文件有三列,以此為時(shí)間戳、操作類型和文件ID(不帶group名稱)

文件操作類型采用單個(gè)字母編碼,其中源頭操作用大寫字母表示,被同步的操作作為對應(yīng)的小鞋字母
C:上傳文件(upload)
D:刪除文件(delete)
A:追加文件(append)
M:部分文件更新(modify)
U:整個(gè)文件更新(set metadata)
T:截?cái)辔募╰runcate)
L:創(chuàng)建符號連接(文件去重功能,相同內(nèi)容的只保存一份)

同組內(nèi)的storage server之間是對等的,文件上傳、刪除等操作可以在任意一臺storage server上進(jìn)行。文件同步只在同組內(nèi)的storage server之間進(jìn)行,采用push方式,即源頭服務(wù)器同步給本組的其他存儲(chǔ)服務(wù)器。對于同組的其他storage server,一臺storage server分別啟動(dòng)一個(gè)線程進(jìn)行文件同步。

文件同步采用增量方式,記錄已同步的位置到mark文件中。mark文件存放路徑為 $base_path/data/sync/。mark文件內(nèi)容示例:

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

采用binlog的異步復(fù)制方式,必然存在同步延遲的問題,比如MySQL的主從數(shù)據(jù)同步。

數(shù)據(jù)恢復(fù)

單盤數(shù)據(jù)恢復(fù)

當(dāng)我們Group中一個(gè)storage磁盤存在損壞的時(shí)候,我們想更換磁盤的時(shí)候,磁盤換上之后自動(dòng)恢復(fù)數(shù)據(jù)。
如何判斷是否需要單盤數(shù)據(jù)恢復(fù):檢測$Store_path/data目錄下的兩個(gè)子目錄00/00 和FF/FF (每級子目錄采用默認(rèn)256個(gè)的情況下)是否存在,若其中一個(gè)不存在,則自動(dòng)建立所需子目錄,并啟動(dòng)單盤數(shù)據(jù)自動(dòng)恢復(fù)。
單盤數(shù)據(jù)恢復(fù)邏輯:

  • 1,從tracker server獲取一臺可用的storage server 做為源服務(wù)器;
  • 2,從storage server拉取該存儲(chǔ)路徑(store_path順序?qū)?yīng))的binlog,并存儲(chǔ)到本地
  • 3,更具本地binlog從源storage server復(fù)制文件到$store_path/data/下對應(yīng)目錄;
  • 4,單盤數(shù)據(jù)恢復(fù)完成后才能對外提供服務(wù)。

Docker 安裝FastDFS

啟動(dòng)前分析

我們這邊采用season/fastdfs:1.2 這個(gè)鏡像,我們獲取他的dockerfile看一下是如何啟動(dòng)的

cat > Obtain_dockerfile.sh <<-'EOF'
#!/bin/bash
#DOC 這是一個(gè)通過docker images 來獲取dockerfile,看一下怎么啟動(dòng)的
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

執(zhí)行腳本獲取到的dockerfile如下

# 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"]}

可以看到我們啟動(dòng)都是執(zhí)行這個(gè)腳本來實(shí)現(xiàn)的,我們現(xiàn)在來看一下這個(gè)腳本里面的內(nèi)容如下:

#!/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=()
    #循環(huán)讀取配置文件
    while read line
    do
        array[$n]="${line}";
        ((n++));
    done < /fdfs_conf/tracker.conf

    rm "$TRACKER_CONF_FILE"
    #${!array[@]} 為數(shù)組的下標(biāo)
    for i in "${!array[@]}"; do
        #判斷組名是否為空
        if [ ${STORE_GROUP} ]; then
            #如果不為空,則判斷是否包含storage_group 這個(gè)字段,然后把這行地?fù)Q掉
            [[ "${array[$i]}" =~ "store_group=" ]] && array[$i]="store_group=${STORE_GROUP}"
        fi
        # 循環(huán)追加配置
        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;"

我們簡單的分析下這個(gè)腳本,發(fā)現(xiàn)這個(gè)腳本是按照啟動(dòng)后面?zhèn)鬟f的參數(shù)來判斷是啟動(dòng)trakcer、storage還是nginx,腳本什么的我們也看了 現(xiàn)在來啟動(dòng)測試下

啟動(dòng)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

啟動(dòng)之后tracker 會(huì)監(jiān)聽在22122 上,我們也可以通過傳遞環(huán)境變量的方式來更改端口

-e port=22222

所有配置文件里面的配置我們都可以通過環(huán)境變量的方式傳遞進(jìn)去

#tracker 可以傳遞的環(huán)境變量和默認(rèn)值
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

啟動(dòng)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

可傳遞的環(huán)境變量

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

測試fastdfs

進(jìn)入到tracker容器里面

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

#使用下面命令查看fastdfs集群狀態(tài)
fdfs_monitor /etc/fdfs/client.conf
#上傳一個(gè)文件測試下
fdfs_upload_file /etc/fdfs/client.conf /etc/hosts
    group1/M00/00/00/rBABql33W5CAK7yFAAAAnrLoM8Y9254622

#下載文件
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

#刪除文件
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/rBABql33W5CAK7yFAAAAnrLoM8Y9254622

啟動(dòng)nginx給別的程序訪問使用

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

注意:

```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;
}
}

可更改的配置文件

```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 要和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

集群搭建

我們只需要在另外一臺機(jī)器啟動(dòng)storage和nginx即可,然后做個(gè)負(fù)載均衡為所有的

網(wǎng)站欄目:FastDFS分布式文件存儲(chǔ)
鏈接URL:http://www.muchs.cn/article34/ijsese.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、響應(yīng)式網(wǎng)站、云服務(wù)器、ChatGPT企業(yè)建站、網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)