利用 MinIO 輕鬆搭建靜態資源服務

如果想搭建一個優雅、簡單、功能完備的靜態資源服務,那就用MinIO吧。

1 引言

開發 Web 項目過程中,經常需要處理靜態資源(如圖片、視頻、音頻,js庫 ,css 庫等),一般來說,若項目中需要用到這些資源文件,我們常用的有以下幾種方法:

  • 本地存儲:即在項目工程中的 static 目錄下,建立 js/css/icon/font/image/lib/audio/video 等目錄,分別存放對應格式的資源文件。使用時,在 html 文件中使用相對位置引用進行。
  • 使用代理搭建靜態資源服務:即把資源存放於某一文件目錄,使用代理服務器(如 nginx ,apache等)對目錄進行映射,構建成資源服務。使用時,在 html 文件中使用代理服務的 url 地址進行引用。
  • 使用第三方工具搭建靜態資源服務:使用第三方開源的文件存儲或對象存儲工具,或者自己寫個程序實現可以獲取文件的接口。使用時,使用對應的 url 地址或接口地址。
  • 使用在線靜態資源服務:如阿里雲、CDN等服務。

對於本地存儲,缺點就很明顯,資源與代碼文件混合一起,沒有必要,而且不方便擴展。對於本地內部部署的應用,顯然是自己搭建靜態資源服務比較穩妥。對於使用代理服務和第三方工具,相比起來,代理服務僅做映射,雖然可用,但功能單一,僅做映射,沒有其它管理功能,也不方便擴展。使用第三方文件或對象存儲工具,可以對文件進行管理、也能考慮高擴展,高性能、高可用等因素,因此是很好的選擇,其中,MinIO 就是這樣一款好用的對象存儲工具,簡單,快捷而且功能完備。

本文則是通過對 MinIO 的安裝、配置與使用,構建靜態資源服務,從而把圖片、視頻、音頻,第三方 js 庫等資源獨立部署,訪問;還會對 MinIO 提供的 Java API 進行使用簡單介紹,以便於進一步開發。

2 MinIO 簡介

MinIO 官方介紹,MinIO 是高性能的對象存儲(塊存儲、文件存儲和對象存儲的區別,可參考架構師都知道的分佈式對象存儲解決方案),兼容 Amazon S3 接口,充分考慮開發人員的需求和體驗;支持分佈式存儲,具備高擴展性、高可用性;部署簡單但功能豐富。官方的文檔也很詳細。它有多種不同的部署模式(單機部署,分佈式部署)。爲什麼說 MinIO 簡單易用,原因就在於它的啓動、運行和配置都很簡單。可以通過 docker 方式進行安裝運行,也可以下載二進制文件,然後使用腳本運行。

本文以最簡單的方式進行講解,在 linux 機器中,單機部署,運行二進制文件。

3 MinIO 運行與靜態資源使用

3.1 MinIO 獲取

MinIO 開發文檔中,下載地址如下:

  • linux: https://dl.min.io/server/minio/release/linux-amd64/minio
  • windows: https://dl.min.io/server/minio/release/windows-amd64/minio.exe

本文在 linux 中運行。

3.2 MinIO 啓動與運行

3.2.1 前臺簡單啓動

把下載的 minio 文件存放到某個目錄作爲運行目錄(如 /opt/minio),新建一個目錄(如/opt/minio-data)作爲 minio 數據存儲位置,即可啓動,如下腳本:

cd /opt/minio
chmod +x minio
./minio server /opt/minio-data

啓動後會輸出訪問地址 endpoint 和對應的 access_key 和 secret_key,使用瀏覽器訪問 endpoint 地址,若可以訪問,則表示 minio 已經安裝成功。不過這樣啓動會有幾個缺點:

  • 不是後臺運行,ctrl+c 就會結束進程,服務就停止
  • 沒有自定義訪問的用戶名密碼
  • 沒有指定訪問IP和端口
  • 日誌沒有保留到文件

針對這些問題,建議使用下面的方式進行啓動運行。

3.2.2 後臺指定參數運行

使用 nohup 在後臺運行程序,同時指定密碼參數,訪問地址參數和日誌輸出,如下所示。

MINIO_ACCESS_KEY=minio MINIO_SECRET_KEY=minio123 nohup /opt/minio/minio  server --address "${MINIO_HOST}:${MINIO_PORT}" /opt/minio-data  > /opt/minio/minio.log 2>&1 &

MINIO_ACCESS_KEYMINIO_SECRET_KEY 是訪問密碼

${MINIO_HOST}:${MINIO_PORT} 分別是訪問的 host 和端口,請按實際情況修改。

這樣,通過瀏覽器訪問地址 ${MINIO_HOST}:${MINIO_PORT} ,使用指定的 MINIO_ACCESS_KEYMINIO_SECRET_KEY 登錄即可。

3.2.3 創建 bucket 並指定訪問策略

在瀏覽器中登錄到 MinIO 存儲系統,點擊右下角創建 bucket 來存儲對象,分別創建對應的 bucket 以存放靜態資源:image,video,audio。這樣,就可以按資源類型在對應的 bucket 中進行文件上傳了,上傳後可以把文件分享,其它地方可以通過分享的 url 獲取資源,如下圖所示。

分享文件

MinIO 默認的策略是分享地址的有效時間最多是7天,要突破這種限制,可以在 bucket 中進行策略設置。點擊對應的 bucket ,edit policy 添加策略 *.*Read Only,如下:

edit policy

如此就放開了訪問,沒有時間限制,同時只需要按http://${MINIO_HOST}:${MINIO_PORT}/${bucketName}/${fileName} 則可直接訪問資源(不需要進行分享操作)。

關於 MinIO 目錄的誤區

  • 其實對於對象存儲來說,其實不區分文件還是目錄,所有文件和目錄都是對象,即 image/temp/xxx.jpg 和 image/temp/ 都是對象。它跟操作系統的文件系統的樹狀結構有本質區別。
  • 上傳文件時,objectName 可以是 /temp/xxx.jpg,可以認爲系統自動創建了temp目錄。
  • MinIO 不會提供像刪除目錄,同時刪除此目錄下所有文件的操作(即 rm -rf image/temp),因此要想把目錄 image/temp 刪除,則需要先把以 image/temp 爲前綴的所有文件刪除。
  • 查詢多個文件時,可以使用前綴匹配方式獲取,見 API 文檔 listObjects(bucketName, prefix, recursive)

3.3 在 html 文件中引用靜態資源

通過上面的設置與運行,MinIO 作爲靜態資源服務器已經完成,可以寫個 html 來引用 MinIO 中的靜態資源。如下是測試的 html 裏面的圖片、視頻、音頻均使用 MinIO 的資源地址。

<div class="img-list">
        <img src="http://${MINIO_HOST}:${MINIO_PORT}/image/test.jpg" alt="圖片">
    </div>
    <div class="audio-list">
        <audio src="http://${MINIO_HOST}:${MINIO_PORT}/audio/test.mp3"
        controls="controls"></audio>
    </div>
    <div class="video-list">
        <video src="http://${MINIO_HOST}:${MINIO_PORT}/video/test.mp4" controls="controls"></video>
    </div>

可發現資源是可以正常加載訪問的。

4 Java 客戶端 API 操作

MinIO 對開發者是非常友好的,提供了各種語言的 API 操作接口,具體可以參考 MinIO開發文檔。下面以 Java 爲例做一下測試。

4.1 添加依賴

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>6.0.13</version>
</dependency>

4.2 使用 Java API 進行文件操作

建立 MinIO 的操作客戶端 minioClient = new MinioClient(endpoint, accessKey, secretKey);,參數中endpoint 是 MinIO 的訪問地址,後面兩對應啓動時設置的密碼。

4.2.1 上傳文件

/**
 * 上傳文件
 * @param minioClient 操作客戶端
 * @param bucketName 上傳的bucket名稱 
 * @param objectName 上傳後存儲在bucket中的文件名
 * @param filePath 上傳的本地文件路徑
 */
public void uploadFile(MinioClient minioClient, String bucketName, String objectName, String filePath) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
    try {
        // 若不存在bucket,則新建
        boolean isExist = minioClient.bucketExists(bucketName);
        if (!isExist) {
            minioClient.makeBucket(bucketName);
        }
        // 使用 putObject 上傳文件
        minioClient.putObject(bucketName, objectName, filePath, null, null, null, null);
    } catch (MinioException e) {
        System.out.println("Error occurred: " + e);
    }
}

4.2.2 下載文件

/**
 * 下載文件
 *
 * @param minioClient 操作客戶端
 * @param bucketName 上傳的bucket名稱 
 * @param objectName 上傳後存儲在bucket中的文件名
 * @param downloadPath 下載文件保存路徑
 */
public void downloadFile(MinioClient minioClient, String bucketName, String objectName, String downloadPath) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
    File file = new File(downloadPath);
    try (OutputStream out = new FileOutputStream(file)) {
        InputStream inputStream = minioClient.getObject(bucketName, objectName);
        byte[] tempbytes = new byte[1024];
        int byteread = 0;
        while ((byteread = inputStream.read(tempbytes)) != -1) {
            out.write(tempbytes, 0, byteread);
        }
    } catch (MinioException e) {
        System.out.println("Error occurred: " + e);
    }
}

4.2.3 刪除文件

刪除文件簡單,使用removeObject即可。

minioClient.removeObject(bucketName, objectName);

4.2.4 列出文件

/**
  * 羅列文件
  * @param minioClient
  * @param bucketName
  */
public void listFile(MinioClient minioClient, String bucketName) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
    try {
        Iterable<Result<Item>> results = minioClient.listObjects(bucketName);
        Iterator<Result<Item>> iterator = results.iterator();
        while (iterator.hasNext()) {
            Item item = iterator.next().get();
            System.out.println(item.objectName() + ", " + item.objectSize() + "B");
        }
    } catch (MinioException e) {
        System.out.println("Error occurred: " + e);
    }
}

5 總結

由於有對靜態資源進行獨立訪問的需求,進行動靜分離,通過使用 MinIO ,可以快速簡單的實現靜態資源服務器,以供訪問。本文通過對 MinIO 的下載、部署、啓動、運行、配置等描述,並以 html 引用靜態資源文件爲例,講解 MinIO 的使用,並提供 Java API 的簡單使用。希望對大家有幫助。

資源下載

本文中使用了 nohup 對 MinIO 進行啓動,但命令太長,一般我們都會寫成腳本,以實現啓動、關閉及狀態查詢,因此,我把腳本寫成完整的 sh 文件,以供大家使用。另外,MinIO Java API 的測試,本示例使用的是 Spring Boot 項目,以單元測試的方式進行。

sh腳本文件及 Spring Boot 工程一起放在我的 minio github 示例 中(腳本minio-serviced.sh 在 scripts 目錄下),有需要的可下載參考。

腳本使用方法:

  • 根據實際情況修改sh腳本中的參數
  • 修改執行權限:chmod +x minio-serviced.sh
  • 按參數啓動/關閉/重啓/運行狀態:./minio-serviced.sh start/stop/restart/status

參考資料

往期文章

我的公衆號(搜索Mason技術記錄),獲取更多技術記錄:

mason

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章