聽說你 FastDFS 老安裝失敗,這能忍?鬆哥一定要幫你搞定

1.什麼是 FastDFS

1.1 FastDFS 簡介

FastDFS 由淘寶的餘慶大佬在 2008 年開源的一款輕量級分佈式文件管理系統,FastDFS 用 C 語言實現,支持 Linux、FreeBSD、MacOS 等類 UNIX 系統。FastDFS 類似 google FS,屬於應用級文件系統,不是通用的文件系統,只能通過專有 API 訪問,目前提供了 C 和 Java SDK ,以及 PHP 擴展 SDK。

這款開源軟件從發佈至今,歷經數十年,這款開源軟件的生命力依然旺盛,在業界依然備受推崇,當然這也得益於作者一直在不斷完善該軟件。

FastDFS 專為互聯網應用量身定做,解決大容量文件存儲問題,追求高性能和高擴展性,它可以看做是基於文件的 key/value 存儲系統,key 為文件 ID,value 為文件內容,因此稱作分佈式文件存儲服務更為合適。

1.2 為什麼需要 FastDFS

傳統的企業級開發對於高併發要求不是很高,而且數據量可能也不大,在這樣的環境下文件管理可能非常 Easy。

但是互聯網應用訪問量大、數據量大,在互聯網應用中,我們必須考慮解決文件大容量存儲和高性能訪問的問題,而 FastDFS 就特別適合幹這件事情,常見的圖片存儲、視頻存儲、文檔存儲等等我們都可以採用 FastDFS 來做。

1.3 FastDFS 架構

作為一款分佈式文件管理系統,FastDFS 主要包括四個方面的功能:

  • 文件存儲
  • 文件同步
  • 文件上傳
  • 文件下載

這個方面的功能,基本上就能搞定我們常見的文件管理需求了。

下面這是一張來自 FastDFS 官網的系統架構圖:

聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

從上面這張圖中我們可以看到,FastDFS 架構包括 Tracker 和 Storage 兩部分,看名字大概就能知道,Tracker 用來追蹤文件,相當於是文件的一個索引,而 Storage 則用來保存文件。

我們上傳文件的文件最終保存在 Storage 上,文件的元數據信息保存在 Tracker 上,通過 Tracker 可以實現對 Storage 的負載均衡。

Storage 一般會搭建成集群,一個 Storage Cluster 可以由多個組構成,不同的組之間不進行通信,一個組又相當於一個小的集群,組由多個 Storage Server 組成,組內的 Storage Server 會通過連接進行文件同步來保證高可用。

2.FastDFS 安裝

介紹完 FastDFS 之後,相信小夥伴已經摩拳擦掌躍躍欲試了,接下來我們就來看下 FastDFS 的安裝。

我這裡為了測試方便,就不開啟多臺虛擬機了,Tracker 和 Storage 我將安裝在同一臺服務器上。

圖片上傳我們一般使用 FastDFS,圖片上傳成功之後,接下來的圖片訪問我們一般採用 Nginx,所以這裡的安裝我將從三個方面來介紹:

  • Tracker 安裝
  • Storage 安裝
  • Nginx 安裝

2.1 Tracker 安裝

安裝,我們首先需要準備一個環境兩個庫以及一個安裝包。

「1.一個環境」

先來看一個環境,由於 FastDFS 採用 C 語言開發,所以在安裝之前,如果沒有 gcc 環境,需要先安裝,安裝命令如下:

<code>yum install gcc-c++/<code>

「2.兩個庫」

再來看兩個庫,由於 FastDFS 依賴 libevent 庫,安裝命令如下:

<code>yum -y install libevent/<code>

另一個庫是 libfastcommon,這是 FastDFS 官方提供的,它包含了 FastDFS 運行所需要的一些基礎庫。

libfastcommon 下載地址:https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz

考慮到 GitHub 訪問較慢,松哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們可以在松哥公眾號後臺回覆 fastdfs 獲取下載鏈接。

將下載好的 libfastcommon 拷貝至 /usr/local/ 目錄下,然後依次執行如下命令:

<code>cd /usr/local
tar -zxvf V1.0.43.tar.gz
cd libfastcommon-1.0.43/
./make.sh
./make.sh install/<code>

「3.一個安裝包」

接下來我們下載 Tracker,注意,由於 Tracker 和 Storage 是相同的安裝包,所以下載一次即可(2.2 小節中不用再次下載)。

安裝文件可以從 FastDFS 的 GitHub 倉庫上下載,下載地址:https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz

考慮到 GitHub 訪問較慢,松哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們可以在松哥公眾號後臺回覆 fastdfs 獲取下載鏈接。

下載成功後,將下載文件拷貝到 /usr/local 目錄下,然後依次執行如下命令安裝:

<code>cd /usr/local
tar -zxvf V6.06.tar.gz
cd fastdfs-6.06/
./make.sh
./make.sh install/<code>

安裝成功後,執行如下命令,將安裝目錄內 conf 目錄下的配置文件拷貝到 /etc/fdfs 目錄下:

<code>cd conf/
cp ./* /etc/fdfs//<code>

「4.配置」

接下來進入 /etc/fdfs/ 目錄下進行配置:

打開 tracker.conf 文件:

<code>vi tracker.conf/<code>

修改如下配置:

聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

默認端口是 22122,可以根據實際需求修改,我這裡就不改了。然後下面配置一下元數據的保存目錄(注意目錄要存在)。

「5.啟動」

接下來執行如下命令啟動 Tracker:

<code>/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start/<code>

如此之後,我們的 Tracker 就算安裝成功了。

2.2 Storage 安裝

簡單起見,這裡我們搭建一個 Storage 實例即可。Storage 安裝也需要 libevent 和 libfastcommon,這兩個庫的安裝參考上文,這裡我不在細說。

Storage 本身的安裝,也和 Tracker 一致,執行命令也都一樣,因為我這裡將 Tracker 和 Storage 安裝在同一臺服務器上,所以不用再執行安裝命令了(相當於安裝 Tracker 時已經安裝了 Storage 了)。

唯一要做的,就是進入到 /etc/fdfs 目錄下,配置 Storage:

<code>vi storage.conf/<code>
聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

這裡一共配置三個地方,分別是 base_path、store_path0 以及 tracker_server ,tracker_server 模板有兩個地址,我們這裡只有一個,配置完成後,記得註釋掉另外一個不用的。

配置完成後,執行如下命令啟動 Storage:

<code>/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start/<code>

這兩個啟動完成後,現在就可以做文件的上傳了,但是一般如果是圖片文件,我們還需要提供一個圖片的訪問功能,目前來說最佳方案當然是 Nginx 了,所以我們這裡連同 Nginx 一起配置好,再來做測試。

2.3 Nginx 安裝

Nginx 可以算是 FastDFS 的重要搭檔。

Nginx 的安裝分為兩個步驟:

  • 安裝 Nginx
  • 首先在 Storage 下安裝 fastdfs-nginx-module

第一步簡單,松哥之前專門寫過一篇文章掃盲 Nginx,所以 Nginx 安裝大家直接參考這裡:Nginx 極簡入門教程!

接下來看第二步。

首先下載 fastdfs-nginx-module,下載地址:https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz

考慮到 GitHub 訪問較慢,松哥已經把安裝文件下載好了,放在百度網盤上,小夥伴們可以在松哥公眾號後臺回覆 fastdfs 獲取下載鏈接。

下載完成後,將下載的文件拷貝到 /usr/local 目錄下。然後進入 /usr/local 目錄,分別執行如下命令:

<code>cd /usr/local
tar -zxvf V1.22.tar.gz/<code>

然後將 /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf文件拷貝到 /etc/fdfs/ 目錄下,並修改該文件的內容:

<code>vi /etc/fdfs/mod_fastdfs.conf/<code>
聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

接下來,回到第一步下載的 nginx 安裝文件的解壓目錄中,執行如下命令,重新配置編譯安裝:

<code>./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src
make
make install/<code>

安裝完成後,修改 nginx 的配置文件,如下:

<code>vi /usr/local/nginx/conf/nginx.conf/<code>
聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

在這裡配置 nginx 請求轉發。

配置完成後,啟動 nginx,看到如下日誌,表示 nginx 啟動成功:

<code>ngx_http_fastdfs_set pid=9908/<code>

「疑問:fastdfs-nginx-module 有啥用」

看了整個安裝過程之後,很多小夥伴有疑問,到頭來還是 nginx 本身直接找到了圖片文件目錄,fastdfs-nginx-module 到底有啥用?

前面我們說過,Storage 由很多組構成,每個組又是一個小的集群,在每一個組裡邊,數據會進行同步,但是如果數據還沒同步,這個時候就有請求發來了,該怎麼辦?此時fastdfs-nginx-module 會幫助我們直接從源 Storage 上獲取文件。

安裝成功了。

3.Java 客戶端調用

安裝成功後,接下來我們就用 Java 客戶端來測試一下文件上傳下載。

首先我們來創建一個普通的 Maven 工程,添加如下依賴:

<code><dependency>
<groupid>net.oschina.zcx7878/<groupid>
<artifactid>fastdfs-client-java/<artifactid>
<version>1.27.0.0/<version>
/<dependency>/<code>

然後,在項目的 resources 目錄下添加 FastDFS 的配置文件 fastdfs-client.properties,內容如下:

<code>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/<code>

這裡的配置基本上都能見名知義,我就不挨個解釋了。這裡先配置下 fastdfs.tracker_servers,這是 Tracker 的地址,根據實際情況配置即可。

fastdfs.http_secret_key 配置這裡先不用管它,後面我會跟大家解釋。

3.1 文件上傳

配置完成後,先來看文件上傳,代碼如下:

<code>@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();
}
}/<code>

這裡,首先加載配置文件,然後構造一個 TrackerClient 對象,接著再根據這個對象獲取到一個 TrackerServer,然後創建一個 StorageClient1 實例。NameValuePair 中保存的是文件的元數據信息,如果有的話,就以 key/value 的方式來設置,如果沒有的話,直接給一個 null 即可。

最後,調用 client 的 upload_file1 方法上傳文件,第一個參數是文件路徑,第二個參數是文件的擴展名,第三個參數就是文件的元數據信息,這個方法的返回值,就是上傳文件的訪問路徑。執行該方法,打印日誌如下:

<code>2020-02-29 17:46:03.017  INFO 6184 --- [           main] o.j.fastdfs.FastdfsApplicationTests      : group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png/<code>

group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就是文件的路徑,此時,在瀏覽器中輸入 http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就可以看到上傳的圖片了。

3.2 文件下載

<code>@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();
}
}/<code>

這段代碼就很好理解了,直接調用 download_file1 方法獲取到一個 byte 數組,然後通過 IO 流寫出到本地文件即可。

4.安全問題

現在,任何人都可以訪問我們服務器上傳文件,這肯定是不行的,這個問題好解決,加一個上傳時候的令牌即可。

首先我們在服務端開啟令牌校驗:

<code>vi /etc/fdfs/http.conf/<code>
聽說你 FastDFS 老安裝失敗,這能忍?松哥一定要幫你搞定

配置完成後,記得重啟服務端:

<code>./nginx -s stop
./nginx/<code>

接下來,在前端準備一個獲取令牌的方法,如下:

<code>@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());
}/<code>

這裡,我們主要是根據 ProtoCommon.getToken 方法來獲取令牌,注意這個方法的第一個參數是你要訪問的文件 id,**注意,這個地址裡邊不包含 group,千萬別搞錯了;**第二個參數是時間戳,第三個參數是密鑰,密鑰要和服務端的配置一致。

將生成的字符串拼接,追加到訪問路徑後面,如:http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png?token=7e329cc50307000283a3ad3592bb6d32&ts=1582975854。「此時訪問路徑裡邊如果沒有令牌,會訪問失敗。」

好了,大功告成!下次和大家講我如何在 Spring Boot 中玩這個東西。

原文鏈接:https://mp.weixin.qq.com/s/onZmdgi9kZw0JdAtrNYmow


分享到:


相關文章: