如果想搭建一個優雅、簡單、功能完備的靜態資源服務,那就用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_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 獲取資源,如下圖所示。
MinIO 默認的策略是分享地址的有效時間最多是7天,要突破這種限制,可以在 bucket 中進行策略設置。點擊對應的 bucket ,edit policy
添加策略 *.*
,Read Only
,如下:
如此就放開了訪問,沒有時間限制,同時只需要按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
參考資料
- MinIO官網:
https://min.io/
- MinIO開發文檔:
https://docs.min.io/
- 基於 Go 開源項目 MIMIO 的對象存儲方案在探探的實踐:
https://mp.weixin.qq.com/s/MzA4ODg0NDkzOA==&mid=2247487119&idx=1&sn=6e09abb32392e015911be3a1d7f066e5&source=41
- 架構師都知道的分布式對象存儲解決方案:
https://juejin.im/post/5cdc16e251882568651553f9
- 使用minio搭建高性能對象存儲:
https://tonybai.com/2020/03/16/build-high-performance-object-storage-with-minio-part1-prototype
往期文章
- 搞定SpringBoot多數據源(3):參數化變更源
- 搞定SpringBoot多數據源(2):動態數據源
- 搞定SpringBoot多數據源(1):多套源策略
- java開發必學知識:動態代理
- 2019 讀過的好書推薦
- springboot+apache前后端分離部署https
- springboot+logback 日志輸出企業實踐(下)
- springboot+logback 日志輸出企業實踐(上)
我的公眾號(搜索Mason技術記錄
),獲取更多技術記錄: