使用FastDFS搭建分布式文件系統(tǒng)

一含思、簡介和應用場景

1.1朋凉、簡介

FastDFS是一款使用純C語言實現的應用級別的分布式文件存儲服務

1.2望拖、架構

FastDFS系統(tǒng)由client(文件上傳下載客戶端)尺铣、tracker(協調服務器)训枢、storage(存儲服務器)三部分組成位迂。
tracker和storage可以進行集群部署琅拌,多個tracker之間并無聯系拄轻,所以tracker彼此間并不存在同步搅裙,僅僅是用做容災皱卓,防止一臺tracker宕機后無法繼續(xù)提供存儲服務。
storage服務啟動后會向配置的tracker server注冊自己部逮,向其報告自己的狀態(tài)信息娜汁,包括磁盤剩余空間、文件同步狀況兄朋、文件上傳下載次數等統(tǒng)計信息掐禁,這使得tracker可以協調多個storage共同工作。不同組的Storage server之間不會相互通信颅和,同組內的Storage server之間會相互連接進行文件同步傅事。

同步方式
Storage server采用binlog文件記錄文件上傳、刪除等更新操作峡扩。binlog中只記錄文件名蹭越,不記錄文件內容。
文件同步只在同組內的Storage server之間進行教届,采用push方式般又,即源頭服務器同步給目標服務器。
 Storage server中由專門的線程根據binlog進行文件同步,Storage server對組內除自己以外的每臺服務器都會啟動一個線程來進行文件同步巍佑。
 文件同步采用增量同步方式,系統(tǒng)記錄已同步的位置(binlog文件偏移量)到標識文件中寄悯。標識文件名格式:{dest storage IP}_{port}.mark萤衰,例如:192.168.1.1_23000.mark。

1.3猜旬、交互流程

上傳:

   客戶端通過API向 tracker  server發(fā)起請求脆栋,獲取當前可用的storage server  地址( 注意:由于多個tracker間并無關聯,此處的負載應由客戶端去處理洒擦〈徽客戶端應獲取所有可用的tracker server,按照一定的均衡策略從中選取一個可用鏈接熟嫩,若此鏈接在一段時間內都不可用秦踪,應將其暫時移除并重新獲取,而且要在一定條件下將其重新加入可選列表)。
   客戶端從tracker server中成功獲取到可用的storage server地址椅邓,然后向此storage server發(fā)起上傳文件的請求柠逞。
   storage server向客戶端返回此文件的path。
   storage server向組內其他兄弟發(fā)起文件同步景馁。

下載:下載一般有兩種板壮,圖片和PDF等瀏覽器自身支持的文件類型,可通過nginx代理直接使用path訪問合住。其他關聯了業(yè)務的附件下載操作應通過應用服務器中轉下載绰精。

    單機情況下若ng和storage server在同一臺服務器,可以通過文件path直接反向映射到本地磁盤文件透葛。
    集群情況下需安裝fastdfs-nginx-module插件笨使,此插件可以自動尋址到上傳文件的源storage server上,防止同步時間差導致請求其他storage server 獲取不到此文件获洲。

1.4 阱表、缺點及應用場景

FastDFS以簡單、易用作為其設計原則贡珊,但這無法避免的產生了一些問題:
數據安全性

1.上傳文件到源服務器即成功最爬,若此時源服務器宕機且處于同步時間差,那么此文件數據會丟失门岔。
2.同步未對文件做正確性校驗爱致,這種同步方式僅適用單個集群點的局部內部網絡,如果在公網上使用寒随,肯定會出現損壞文件的情況糠悯,需要自行添加文件校驗機制(篡改和硬件損壞,幾率極低)妻往。

大文件處理

 FastDFS沒有對文件做分塊存儲互艾,因此不太適合分布式計算場景。(不適合存儲大文件)

綜上所述讯泣,fastDFS適用于處理以小文件為載體纫普、文件安全性不是太苛刻的在線存儲服務,如相冊好渠、視頻等昨稼。

二、安裝及部署

fastdfs

所有服務安裝方式都為源碼編譯安裝拳锚,提供兩種方式下載源碼——github和sourceforge假栓,github上有最新的發(fā)布版本。
github
sourceforge

nginx 緩存插件

ngx_cache_purge

2.1霍掺、環(huán)境依賴

操作系統(tǒng)為4臺64位CentOS Linux release 7.5.1804

192.168.152.136 nginx tracker
192.168.152.139 tracker
192.168.152.134 storage2 ngx_fastdfs_module
192.168.152.135 storage1 ngx_fastdfs_module

依賴第三方工具:

zlib zlib-devel pcre pcre-devel gcc gcc-c++ openssl openssl-devel libevent libevent-devel perl unzip net-tools wget

2.2匾荆、整體架構

線上架構應為:用戶——》keepalived(虛擬IP)——》負載nginx(2+)——》tracker負載nginx(2+)——》
storage(2+)拌蜘,架構圖如下


complete_fdfs.jpg

本次部署只為模擬,進行了簡化,架構圖如下


simple_fdfs.jpg

2.2棋凳、安裝libfastcommon

解壓并安裝


tar -zxvf V1.0.7.tar.gz

cd libfastcommon-1.0.7

./make.sh

./make.sh isntall

軟鏈接動態(tài)鏈接庫到引用路徑


ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so

ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so

ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so

ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so

2.3拦坠、安裝FastDFS

解壓并安裝


tar -zxvf V5.05.tar.gz

cd fastdfs-5.05

./make.sh

./make.sh install

軟連接到腳本到引用路徑


ln -s /usr/bin/fdfs_trackerd  /usr/local/bin

ln -s /usr/bin/fdfs_storaged  /usr/local/bin

ln -s /usr/bin/stop.sh        /usr/local/bin

ln -s /usr/bin/restart.sh      /usr/local/bin

2.4、配置tracker和storage

192.168.152.135 192.168.152.134分別創(chuàng)建 tracker及storage目錄


mkdir -p /home/fdfs/trackerd

mkdir -p /home/fdfs/storaged

配置tracker
  vi /etc/fdfs/tracker.conf

主要配置tracker的元數據和日志存儲路徑和均衡策略等

 #存儲路徑
  base_path=/home/fdfs/fdfs_trackerd
  #下載文件如何選擇storage server
  #0表示輪詢剩岳,1表示上傳的源服務器(避免同步時間差)
  download_server=1
配置storage
  vi /etc/fdfs/storage.conf
#分組名稱
group_name=group1
#數據及日志存儲路徑
base_path=/home/mandy/fdfs/fdfs_storaged
#數據存儲路徑贞滨,可以有多個(可以掛載多個磁盤)
store_path0=/home/fdfs/fdfs_storaged
#tracker server地址,多個寫成列表形式
tracker_server=192.168.152.136:22122
tracker_server = 192.168.152.134:22122

配置完畢啟動服務并驗證

service fdfs_trackerd start
service fdfs_storaged start

查看服務是否已開啟

netstat -unltp | grep fdfs

查看storage是否已經激活到tracker

/usr/bin/fdfs_monitor /etc/fdfs/storage.conf

storage sever狀態(tài)

  # FDFS_STORAGE_STATUS_INIT      :初始化拍棕,尚未得到同步已有數據的源服務器

  # FDFS_STORAGE_STATUS_WAIT_SYNC :等待同步晓铆,已得到同步已有數據的源服務器

  # FDFS_STORAGE_STATUS_SYNCING   :同步中

  # FDFS_STORAGE_STATUS_DELETED   :已刪除,該服務器從本組中摘除(注:本狀態(tài)的功能尚未實現)

  # FDFS_STORAGE_STATUS_OFFLINE   :離線

  # FDFS_STORAGE_STATUS_ONLINE    :在線绰播,尚不能提供服務

  # FDFS_STORAGE_STATUS_ACTIVE    :在線骄噪,可以提供服務

2.5、nginx配置

2.5.1蠢箩、storage nginx配置

由于fastdfs在4.0.5之后的版本中將內置的http服務器移除链蕊,因此想通過http方式訪問storage server,需要在每個storage上配置 nginx和fastdfs-nginx-module;

安裝fastdfs-nginx-module
tar -zxf fastdfs-nginx-module-1.20.tar.gz
cd nginx-1.12.1
./configure --add-module=/home/download/fastdfs-nginx-module-master/src
make&&make install

安裝有可能失敗谬泌,如報如下錯誤 /usr/local/include/fastdfs/fdfs_define.h:15:27: 致命錯誤:common_define.h:沒有那個文件或目錄
解決方式

vim fastdfs-nginx-module-1.20/src/config

編輯
ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/"
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"



./nginx -V 查看fastDFS模塊是否已經添加成功

配置nginx.conf

ng配置灰常簡單,如下:

   server {
        listen       80;
        server_name  lcoalhost;
        location /M00 {
            ngx_fastdfs_module;
         }

    }

從解壓的fastdfs-nginx-module-1.20.tar.gz src下拷貝 mod_fastdfs.conf到/etc/fdfs/下并編輯,目前只針對單個group進行配置

#日志存儲路徑
base_path=/home/fdfs
#url中是否需要組名滔韵,若未分組,可以置為false
url_have_group_name = false
#tracker地址掌实,多個寫成列表形式
tracker_server=192.168.152.134:22122
tracker_server = 192.168.152.136:22122,

重啟nginx即可.

2.5.2 負載nginx配置

安裝nginx插件 ngx_cache_purge
tracker添加一臺負載nginx(此處進行了簡化陪蜻,實際線上應多加一層代理)

  #user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
     sendfile        on;
    tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    
    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;

    client_max_body_size 300m;

    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;

    proxy_buffer_size 16k;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 128k;
   
    proxy_cache_path /home/mandy/nginx/proxy_cache levels=1:2 
    keys_zone=http-cache:500m max_size=10g inactive=30d;
    proxy_temp_path /home/mandy/nginx/proxy_cache/tmp;

    upstream fdfs_group1 {
         server 192.168.152.134:80 weight=1 max_fails=2 fail_timeout=30s;
         server 192.168.152.135:80 weight=1 max_fails=2 fail_timeout=30s;
    }
    

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location /M00 {
            proxy_next_upstream http_502 http_504 error timeout invalid_header;
            proxy_cache http-cache;
            proxy_cache_valid  200 304 12h;
            proxy_cache_key $uri$is_args$args;
            proxy_pass http://fdfs_group1;
            expires 30d;
        }
        
        
        location ~/purge(/.*) {
            allow all;
            proxy_cache_purge http-cache  $1$is_args$args;
        }
    }     
  

}

2.6、防盜鏈

fastDFS內置防盜鏈是在服務端開啟token驗證贱鼻,客戶端根據文件名宴卖、當前unix時間戳、秘鑰獲取token邻悬,在地址中帶上token參數即可通過http方式訪問文件症昏。
服務端開啟認證
拷貝fastdfs安裝包conf下的anti-steal.jpg mime.types http.conf文件到 /etc/fdfs/
編輯http.conf

#開啟token
http.anti_steal.check_token=true
#token有效期,單位秒(意味著客戶端時間要與服務器保持在此時間差以內)
http.anti_steal.token_ttl=900
#加密的key
http.anti_steal.secret_key=FastDFS1234567890

同時需要在 mod_fastdfs.conf中配置認證失敗后跳轉的403頁面
客戶端token生成

 public static void main(String[] args){
        #file_path不帶分組名,時間為unix時間父丰,key與服務器http.conf配置的key保持一致
        getToken("M00/00/00/wKiYhluV1heAAJDLAAnTlA5XnbM950.pdf",(int) Instant.now().getEpochSecond(),"FastDFS1234567890");
    }
 public static String md5(byte[] source) throws NoSuchAlgorithmException {
        char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(source);
        byte[] tmp = md.digest();
        char[] str = new char[32];
        int k = 0;

        for(int i = 0; i < 16; ++i) {
            str[k++] = hexDigits[tmp[i] >>> 4 & 15];
            str[k++] = hexDigits[tmp[i] & 15];
        }

        return new String(str);
    }

    public static String getToken(String remote_filename, int ts, String secret_key) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        final String charSet = "UTF-8";
        byte[] bsFilename = remote_filename.getBytes(charSet);
        byte[] bsKey = secret_key.getBytes(charSet);
        byte[] bsTimestamp = (new Integer(ts)).toString().getBytes(charSet);
        byte[] buff = new byte[bsFilename.length + bsKey.length + bsTimestamp.length];
        System.arraycopy(bsFilename, 0, buff, 0, bsFilename.length);
        System.arraycopy(bsKey, 0, buff, bsFilename.length, bsKey.length);
        System.arraycopy(bsTimestamp, 0, buff, bsFilename.length + bsKey.length, bsTimestamp.length);
        return md5(buff);
    }

三齿兔、客戶端集成

目前客戶端使用連接池方式進行調用,首先進行配置:
新建config類并繼承GenericKeyedObjectPoolConfig础米,樣例如下:

@Component
@ConfigurationProperties(prefix = "fastdfs.pool")
public class FastdfsPoolConfig extends GenericKeyedObjectPoolConfig {
}

FastDFSConfig添加對FastdfsExecutor的配置,樣例如下:

@Configuration
public class FastDFSConfig {
    @Resource
    private FastdfsPoolConfig fastdfsPoolConfig;

    @Bean
    public FastdfsExecutor fastdfsExecutor() {
        FastdfsExecutor executor = new FastdfsExecutor();
        executor.setPoolConfig(fastdfsPoolConfig);
        return executor;
    }

    @Bean
    public SimpleFastdfsClient simpleFastdfsClient(FastdfsExecutor fastdfsExecutor, @Value("${fastdfs.tracker.host}") String trackerServerAddr) {
        return new SimpleFastdfsClient(fastdfsExecutor, trackerServerAddr);
    }
}

默認開啟對每次獲取的連接的校驗testOnBorrow =true,若需改為輪詢方式添诉,在spring配置文件中添加如下配置:

 fastdfs.pool.testOnBorrow=false  
 fastdfs.pool.testWhileIdle=true #開啟定時任務校驗空閑連接
 fastdfs.pool.timeBetweenEvictionRunsMillis=30000 #任務間隙屁桑,單位為毫秒
 fastdfs.pool.maxTotalPerKey=10 #每個key最大連接數
 fastdfs.pool.minIdlePerKey=3 #每個key最小空閑連接
 fastdfs.pool.numTestsPerEvictionRun=3 #每次檢測空閑連接數

上傳樣例:

  simpleFastdfsClient.upload(new File("E://data//1.pdf"));

四、遺留問題

使用nginx做文件下載服務器存在一個問題:
文件被刪除后栏赴,由于nginx服務器對已經訪問過的文件進行了緩存蘑斧,那么此文件在一定時間內還是可以被成功下載,即便fastDFS服務已經關閉。
此文題已經解決竖瘾,安裝ngx_cache_purge 插件沟突,訪問“~/purge/資源”即可刪除此文件

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捕传,隨后出現的幾起案子惠拭,更是在濱河造成了極大的恐慌,老刑警劉巖庸论,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件职辅,死亡現場離奇詭異,居然都是意外死亡聂示,警方通過查閱死者的電腦和手機域携,發(fā)現死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鱼喉,“玉大人秀鞭,你說我怎么就攤上這事】盖荩” “怎么了锋边?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵旋圆,是天一觀的道長宠默。 經常有香客問我,道長,這世上最難降的妖魔是什么刻肄? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮粹淋,結果婚禮上吸祟,老公的妹妹穿的比我還像新娘瑟慈。我一直安慰自己,他們只是感情好屋匕,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布葛碧。 她就那樣靜靜地躺著,像睡著了一般过吻。 火紅的嫁衣襯著肌膚如雪进泼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天疮装,我揣著相機與錄音缘琅,去河邊找鬼。 笑死廓推,一個胖子當著我的面吹牛刷袍,可吹牛的內容都是我干的。 我是一名探鬼主播樊展,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呻纹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了专缠?” 一聲冷哼從身側響起雷酪,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涝婉,沒想到半個月后哥力,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡墩弯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年吩跋,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渔工。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡锌钮,死狀恐怖,靈堂內的尸體忽然破棺而出引矩,到底是詐尸還是另有隱情梁丘,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布旺韭,位于F島的核電站氛谜,受9級特大地震影響,放射性物質發(fā)生泄漏区端。R本人自食惡果不足惜值漫,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望珊燎。 院中可真熱鬧惭嚣,春花似錦、人聲如沸悔政。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谋国。三九已至槽地,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芦瘾,已是汗流浹背捌蚊。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留近弟,地道東北人缅糟。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像祷愉,于是被迫代替她去往敵國和親窗宦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內容