提及分佈式文件管理系統,你們可能很容易想到 HDFS、GFS 等系統,前者是 Hadoop 的一部分,後者則是 Google 提供的分佈式文件管理系統。除了這些以外,國內淘寶和騰訊也有本身的分佈式文件管理系統,都叫 TFS(Taobao File System
和 Tencent File System
)。前端
相對於上面提到的這些分佈式文件管理系統而言,FastDFS 可能離咱們 Java 工程師更近一些,由於文件上傳這個功能太常見了,而想要搭建獨立的分佈式文件管理系統,FastDFS+Nginx 組合無疑是最佳方案。所以,鬆哥今天就來和你們簡單聊一聊這個問題。java
若是小夥伴們還不懂在傳統的開發環境下如何進行文件上傳,能夠參考鬆哥以前發的文件上傳教程:nginx
FastDFS 由淘寶的餘慶大佬在 2008 年開源的一款輕量級分佈式文件管理系統,FastDFS 用 C 語言實現,支持 Linux、FreeBSD、MacOS 等類 UNIX 系統。FastDFS 相似 google FS,屬於應用級文件系統,不是通用的文件系統,只能經過專有 API 訪問,目前提供了 C 和 Java SDK ,以及 PHP 擴展 SDK。c++
這款開源軟件從發佈至今,歷經數十年,這款開源軟件的生命力依然旺盛,在業界依然備受推崇,固然這也得益於做者一直在不斷完善該軟件。git
FastDFS 專爲互聯網應用量身定作,解決大容量文件存儲問題,追求高性能和高擴展性,它能夠看作是基於文件的 key/value 存儲系統,key 爲文件 ID,value 爲文件內容,所以稱做分佈式文件存儲服務更爲合適。github
傳統的企業級開發對於高併發要求不是很高,並且數據量可能也不大,在這樣的環境下文件管理可能很是 Easy。數組
可是互聯網應用訪問量大、數據量大,在互聯網應用中,咱們必須考慮解決文件大容量存儲和高性能訪問的問題,而 FastDFS 就特別適合幹這件事情,常見的圖片存儲、視頻存儲、文檔存儲等等咱們均可以採用 FastDFS 來作。瀏覽器
做爲一款分佈式文件管理系統,FastDFS 主要包括四個方面的功能:安全
這個方面的功能,基本上就能搞定咱們常見的文件管理需求了。服務器
下面這是一張來自 FastDFS 官網的系統架構圖:
從上面這張圖中咱們能夠看到,FastDFS 架構包括 Tracker 和 Storage 兩部分,看名字大概就能知道,Tracker 用來追蹤文件,至關因而文件的一個索引,而 Storage 則用來保存文件。
咱們上傳文件的文件最終保存在 Storage 上,文件的元數據信息保存在 Tracker 上,經過 Tracker 能夠實現對 Storage 的負載均衡。
Storage 通常會搭建成集羣,一個 Storage Cluster 能夠由多個組構成,不一樣的組之間不進行通訊,一個組又至關於一個小的集羣,組由多個 Storage Server 組成,組內的 Storage Server 會經過鏈接進行文件同步來保證高可用。
介紹完 FastDFS 以後,相信小夥伴已經摩拳擦掌躍躍欲試了,接下來咱們就來看下 FastDFS 的安裝。
我這裏爲了測試方便,就不開啓多臺虛擬機了,Tracker 和 Storage 我將安裝在同一臺服務器上。
圖片上傳咱們通常使用 FastDFS,圖片上傳成功以後,接下來的圖片訪問咱們通常採用 Nginx,因此這裏的安裝我將從三個方面來介紹:
安裝,咱們首先須要準備一個環境兩個庫以及一個安裝包。
1.一個環境
先來看一個環境,因爲 FastDFS 採用 C 語言開發,因此在安裝以前,若是沒有 gcc 環境,須要先安裝,安裝命令以下:
yum install gcc-c++
2.兩個庫
再來看兩個庫,因爲 FastDFS 依賴 libevent 庫,安裝命令以下:
yum -y install libevent
另外一個庫是 libfastcommon,這是 FastDFS 官方提供的,它包含了 FastDFS 運行所須要的一些基礎庫。
libfastcommon 下載地址:https://github.com/happyfish1...
考慮到 GitHub 訪問較慢,鬆哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們能夠在鬆哥公衆號後臺回覆 fastdfs 獲取下載連接。
將下載好的 libfastcommon 拷貝至 /usr/local/ 目錄下,而後依次執行以下命令:
cd /usr/local tar -zxvf V1.0.43.tar.gz cd libfastcommon-1.0.43/ ./make.sh ./make.sh install
3.一個安裝包
接下來咱們下載 Tracker,注意,因爲 Tracker 和 Storage 是相同的安裝包,因此下載一次便可(2.2 小節中不用再次下載)。
安裝文件能夠從 FastDFS 的 GitHub 倉庫上下載,下載地址:https://github.com/happyfish1...
考慮到 GitHub 訪問較慢,鬆哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們能夠在鬆哥公衆號後臺回覆 fastdfs 獲取下載連接。
下載成功後,將下載文件拷貝到 /usr/local 目錄下,而後依次執行以下命令安裝:
cd /usr/local tar -zxvf V6.06.tar.gz cd fastdfs-6.06/ ./make.sh ./make.sh install
安裝成功後,執行以下命令,將安裝目錄內 conf 目錄下的配置文件拷貝到 /etc/fdfs 目錄下:
cd conf/ cp ./* /etc/fdfs/
4.配置
接下來進入 /etc/fdfs/ 目錄下進行配置:
打開 tracker.conf 文件:
vi tracker.conf
修改以下配置:
默認端口是 22122,能夠根據實際需求修改,我這裏就不改了。而後下面配置一下元數據的保存目錄(注意目錄要存在)。
5.啓動
接下來執行以下命令啓動 Tracker:
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
如此以後,咱們的 Tracker 就算安裝成功了。
簡單起見,這裏咱們搭建一個 Storage 實例便可。Storage 安裝也須要 libevent 和 libfastcommon,這兩個庫的安裝參考上文,這裏我不在細說。
Storage 自己的安裝,也和 Tracker 一致,執行命令也都同樣,由於我這裏將 Tracker 和 Storage 安裝在同一臺服務器上,因此不用再執行安裝命令了(至關於安裝 Tracker 時已經安裝了 Storage 了)。
惟一要作的,就是進入到 /etc/fdfs 目錄下,配置 Storage:
vi storage.conf
這裏一共配置三個地方,分別是 base_path、store_path0 以及 tracker_server ,tracker_server 模板有兩個地址,咱們這裏只有一個,配置完成後,記得註釋掉另一個不用的。
配置完成後,執行以下命令啓動 Storage:
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
這兩個啓動完成後,如今就能夠作文件的上傳了,可是通常若是是圖片文件,咱們還須要提供一個圖片的訪問功能,目前來講最佳方案固然是 Nginx 了,因此咱們這裏連同 Nginx 一塊兒配置好,再來作測試。
Nginx 能夠算是 FastDFS 的重要搭檔。
Nginx 的安裝分爲兩個步驟:
第一步簡單,鬆哥以前專門寫過一篇文章掃盲 Nginx,因此 Nginx 安裝你們直接參考這裏:Nginx 極簡入門教程!
接下來看第二步。
首先下載 fastdfs-nginx-module,下載地址:https://github.com/happyfish1...
考慮到 GitHub 訪問較慢,鬆哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們能夠在鬆哥公衆號後臺回覆 fastdfs 獲取下載連接。
下載完成後,將下載的文件拷貝到 /usr/local 目錄下。而後進入 /usr/local 目錄,分別執行以下命令:
cd /usr/local tar -zxvf V1.22.tar.gz
而後將 /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf
文件拷貝到 /etc/fdfs/
目錄下,並修改該文件的內容:
vi /etc/fdfs/mod_fastdfs.conf
接下來,回到第一步下載的 nginx 安裝文件的解壓目錄中,執行以下命令,從新配置編譯安裝:
./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src make make install
安裝完成後,修改 nginx 的配置文件,以下:
vi /usr/local/nginx/conf/nginx.conf
在這裏配置 nginx 請求轉發。
配置完成後,啓動 nginx,看到以下日誌,表示 nginx 啓動成功:
ngx_http_fastdfs_set pid=9908
疑問:fastdfs-nginx-module 有啥用
看了整個安裝過程以後,不少小夥伴有疑問,到頭來仍是 nginx 自己直接找到了圖片文件目錄,fastdfs-nginx-module 到底有啥用?
前面咱們說過,Storage 由不少組構成,每一個組又是一個小的集羣,在每個組裏邊,數據會進行同步,可是若是數據還沒同步,這個時候就有請求發來了,該怎麼辦?此時fastdfs-nginx-module 會幫助咱們直接從源 Storage 上獲取文件。
安裝成功了。
安裝成功後,接下來咱們就用 Java 客戶端來測試一下文件上傳下載。
首先咱們來建立一個普通的 Maven 工程,添加以下依賴:
<dependency> <groupId>net.oschina.zcx7878</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.27.0.0</version> </dependency>
而後,在項目的 resources 目錄下添加 FastDFS 的配置文件 fastdfs-client.properties,內容以下:
fastdfs.connect_timeout_in_seconds = 5 fastdfs.network_timeout_in_seconds = 30 fastdfs.charset = UTF-8 fastdfs.http_anti_steal_token = false fastdfs.http_secret_key = FastDFS1234567890 fastdfs.http_tracker_http_port = 80 fastdfs.tracker_servers = 192.168.91.128:22122 fastdfs.connection_pool.enabled = true fastdfs.connection_pool.max_count_per_entry = 500 fastdfs.connection_pool.max_idle_time = 3600 fastdfs.connection_pool.max_wait_time_in_ms = 1000
這裏的配置基本上都能見名知義,我就不挨個解釋了。這裏先配置下 fastdfs.tracker_servers,這是 Tracker 的地址,根據實際狀況配置便可。
fastdfs.http_secret_key 配置這裏先不用管它,後面我會跟你們解釋。
配置完成後,先來看文件上傳,代碼以下:
@Test void testUpload() { try { ClientGlobal.initByProperties("fastdfs-client.properties"); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); NameValuePair nvp[] = null; //上傳到文件系統 String fileId = client.upload_file1("C:\\Users\\javaboy\\Pictures\\picpick\\1.png", "png", nvp); logger.info(fileId); } catch (Exception e) { e.printStackTrace(); } }
這裏,首先加載配置文件,而後構造一個 TrackerClient 對象,接着再根據這個對象獲取到一個 TrackerServer,而後建立一個 StorageClient1 實例。NameValuePair 中保存的是文件的元數據信息,若是有的話,就以 key/value 的方式來設置,若是沒有的話,直接給一個 null 便可。
最後,調用 client 的 upload_file1 方法上傳文件,第一個參數是文件路徑,第二個參數是文件的擴展名,第三個參數就是文件的元數據信息,這個方法的返回值,就是上傳文件的訪問路徑。執行該方法,打印日誌以下:
2020-02-29 17:46:03.017 INFO 6184 --- [ main] o.j.fastdfs.FastdfsApplicationTests : group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png
group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就是文件的路徑,此時,在瀏覽器中輸入 http://192.168.91.128/group1/... 就能夠看到上傳的圖片了。
@Test void testDownload() { try { ClientGlobal.initByProperties("fastdfs-client.properties"); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); byte[] bytes = client.download_file1("group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png"); FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\javaboy\\Pictures\\picpick\\666.png")); fos.write(bytes); fos.close(); } catch (Exception e) { e.printStackTrace(); } }
這段代碼就很好理解了,直接調用 download_file1 方法獲取到一個 byte 數組,而後經過 IO 流寫出到本地文件便可。
如今,任何人均可以訪問咱們服務器上傳文件,這確定是不行的,這個問題好解決,加一個上傳時候的令牌便可。
首先咱們在服務端開啓令牌校驗:
vi /etc/fdfs/http.conf
配置完成後,記得重啓服務端:
./nginx -s stop ./nginx
接下來,在前端準備一個獲取令牌的方法,以下:
@Test public void getToken() throws Exception { int ts = (int) Instant.now().getEpochSecond(); String token = ProtoCommon.getToken("M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png", ts, "FastDFS1234567890"); StringBuilder sb = new StringBuilder(); sb.append("?token=").append(token); sb.append("&ts=").append(ts); System.out.println(sb.toString()); }
這裏,咱們主要是根據 ProtoCommon.getToken 方法來獲取令牌,注意這個方法的第一個參數是你要訪問的文件 id,注意,這個地址裏邊不包含 group,千萬別搞錯了;第二個參數是時間戳,第三個參數是密鑰,密鑰要和服務端的配置一致。
將生成的字符串拼接,追加到訪問路徑後面,如:http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png?token=7e329cc50307000283a3ad3592bb6d32&ts=1582975854
。此時訪問路徑裏邊若是沒有令牌,會訪問失敗。
好了,大功告成!下次和你們講我如何在 Spring Boot 中玩這個東西。