1. 程式人生 > >利用 MinIO 輕鬆搭建靜態資源服務

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

[toc] > 如果想搭建一個優雅、簡單、功能完備的靜態資源服務,那就用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](https://min.io/) 官方介紹,MinIO 是高效能的物件儲存(塊儲存、檔案儲存和物件儲存的區別,可參考[架構師都知道的分散式物件儲存解決方案](https://juejin.im/post/5cdc16e251882568651553f9)),相容 Amazon S3 介面,充分考慮開發人員的需求和體驗;支援分散式儲存,具備高擴充套件性、高可用性;部署簡單但功能豐富。官方的文件也很詳細。它有多種不同的部署模式(單機部署,分散式部署)。為什麼說 MinIO 簡單易用,原因就在於它的啟動、執行和配置都很簡單。可以通過 docker 方式進行安裝執行,也可以下載二進位制檔案,然後使用指令碼執行。 本文以最簡單的方式進行講解,在 linux 機器中,單機部署,執行二進位制檔案。 # 3 MinIO 執行與靜態資源使用 ## 3.1 MinIO 獲取 [MinIO 開發文件](https://docs.min.io)中,下載地址如下: - 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 資料儲存位置,即可啟動,如下指令碼: ``` shell 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` 在後臺執行程式,同時指定密碼引數,訪問地址引數和日誌輸出,如下所示。 ```shell 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_KEY` 及 `MINIO_SECRET_KEY` 是訪問密碼 > > `${MINIO_HOST}:${MINIO_PORT}` 分別是訪問的 host 和埠,請按實際情況修改。 這樣,通過瀏覽器訪問地址 `${MINIO_HOST}:${MINIO_PORT}` ,使用指定的 `MINIO_ACCESS_KEY` 及 `MINIO_SECRET_KEY` 登入即可。 ### 3.2.3 建立 bucket 並指定訪問策略 在瀏覽器中登入到 MinIO 儲存系統,點選右下角建立 bucket 來儲存物件,分別建立對應的 bucket 以存放靜態資源:image,video,audio。這樣,就可以按資源型別在對應的 bucket 中進行檔案上傳了,上傳後可以把檔案分享,其它地方可以通過分享的 url 獲取資源,如下圖所示。 ![分享檔案](https://gitee.com/mianshenglee/datastorage/raw/master/md-photo/20200331-minio/share-object.png) MinIO 預設的策略是分享地址的有效時間最多是7天,要突破這種限制,可以在 bucket 中進行策略設定。點選對應的 bucket ,`edit policy` 新增策略 `*.*`,`Read Only`,如下: ![edit policy](https://gitee.com/mianshenglee/datastorage/raw/master/md-photo/20200331-minio/edit-policy.png) 如此就放開了訪問,沒有時間限制,同時只需要按`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 的資源地址。 ``` html
``` 可發現資源是可以正常載入訪問的。 # 4 Java 客戶端 API 操作 MinIO 對開發者是非常友好的,提供了各種語言的 API 操作介面,具體可以參考 [MinIO開發文件](https://docs.min.io/)。下面以 Java 為例做一下測試。 ## 4.1 新增依賴 ```xml io.minio minio 6.0.13 ``` ## 4.2 使用 Java API 進行檔案操作 建立 MinIO 的操作客戶端 `minioClient = new MinioClient(endpoint, accessKey, secretKey);`,引數中`endpoint` 是 MinIO 的訪問地址,後面兩對應啟動時設定的密碼。 ### 4.2.1 上傳檔案 ```java /** * 上傳檔案 * @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 下載檔案 ```java /** * 下載檔案 * * @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`即可。 ```java minioClient.removeObject(bucketName, objectName); ``` ### 4.2.4 列出檔案 ```java /** * 羅列檔案 * @param minioClient * @param bucketName */ public void listFile(MinioClient minioClient, String bucketName) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException { try { Iterable> results = minioClient.listObjects(bucketName); Iterator> 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 示例](https://github.com/mianshenglee/my-example/tree/master/minio-simple-demo) 中(指令碼`minio-serviced.sh` 在 scripts 目錄下),有需要的可下載參考。 > 指令碼使用方法: > > - 根據實際情況修改sh指令碼中的引數 > - 修改執行許可權:chmod +x minio-serviced.sh > - 按引數啟動/關閉/重啟/執行狀態:./minio-serviced.sh start/stop/restart/status # 參考資料 - [MinIO官網](https://min.io/): `https://min.io/` - [MinIO開發文件](https://docs.min.io/): `https://docs.min.io/` - [基於 Go 開源專案 MIMIO 的物件儲存方案在探探的實踐](https://mp.weixin.qq.com/s?__biz=MzA4ODg0NDkzOA==&mid=2247487119&idx=1&sn=6e09abb32392e015911be3a1d7f066e5&source=41):`https://mp.weixin.qq.com/s/MzA4ODg0NDkzOA==&mid=2247487119&idx=1&sn=6e09abb32392e015911be3a1d7f066e5&source=41` - [架構師都知道的分散式物件儲存解決方案](https://juejin.im/post/5cdc16e251882568651553f9):`https://juejin.im/post/5cdc16e251882568651553f9` - [使用minio搭建高效能物件儲存](https://tonybai.com/2020/03/16/build-high-performance-object-storage-with-minio-part1-prototype):`https://tonybai.com/2020/03/16/build-high-performance-object-storage-with-minio-part1-prototype` # 往期文章 - [搞定SpringBoot多資料來源(3):引數化變更源](https://mp.weixin.qq.com/s/ZzzPJZAhPiGCQjN3RNZJ3Q) - [搞定SpringBoot多資料來源(2):動態資料來源](https://mp.weixin.qq.com/s/neIN3htjkn4bifPpdq5l7w) - [搞定SpringBoot多資料來源(1):多套源策略](https://mp.weixin.qq.com/s/0J-FLYScYtEMnj0vZToX7g) - [java開發必學知識:動態代理](https://mp.weixin.qq.com/s/a3x_pKUryb_at_4Xk48IiQ) - [2019 讀過的好書推薦](https://mp.weixin.qq.com/s/Wlbjhohb_HrqT67lstwVwA) - [springboot+apache前後端分離部署https](https://mp.weixin.qq.com/s/hiJdsjdDC07axk-_sAkyVQ) - [springboot+logback 日誌輸出企業實踐(下)](https://mp.weixin.qq.com/s/ha4LaR-E1gDxfUZ11neI-Q) - [springboot+logback 日誌輸出企業實踐(上)](https://mp.weixin.qq.com/s/Ti5i9vv9S1j4za5q11RWeA) 我的公眾號(搜尋`Mason技術記錄`),獲取更多技術記錄: ![mason](https://gitee.com/mianshenglee/datastorage/raw/master/md-photo/myphoto/wx/wx-pub