文章很長,而且持續更新,建議收藏起來,慢慢讀!瘋狂創客圈總目錄 博客園版 為您奉上珍貴的學習資源 :
免費贈送 :《尼恩Java面試寶典》 持續更新+ 史上最全 + 面試必備 2000頁+ 面試必備 + 大廠必備 +漲薪必備
免費贈送 經典圖書:《Java高並發核心編程(卷1)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷2)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷3)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《尼恩Java面試寶典 最新版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 資源寶庫: Java 必備 百度網盤資源大合集 價值>10000元 加尼恩領取
背景:
下一個視頻版本,從架構師視角,尼恩為大家打造高可用、高並發中間件的原理與實操。
目標:通過視頻和博客的方式,為各位潛力架構師,徹底介紹清楚架構師必須掌握的高可用、高並發環境,包括但不限於:
-
高可用、高並發nginx架構的原理與實操
-
高可用、高並發mysql架構的原理與實操
-
高可用、高並發nacos架構的原理與實操
-
高可用、高並發rocketmq架構的原理與實操
-
高可用、高並發es架構的原理與實操
-
高可用、高並發minio架構的原理與實操
why 高可用、高並發中間件的原理與實操:
實際的開發過程中,很多小伙伴聚焦crud開發,環境出了問題,都不能啟動。
作為架構師,或者未來想走向高端開發,或者做架構,必須掌握高可用、高並發中間件的原理,掌握其實操。
本系列博客的具體內容,請參見 Java 高並發 發燒友社群:瘋狂創客圈
分布式文件系統應用場景
互聯網下海量的非結構化存儲的需求背景下,比如:
- 電商網站,存儲海量的商品圖片
- 視頻網站,海量的視頻文件
- 網盤,海量的文件
- 社交網站等等
在這樣的背景下,傳統的FastDFS部署太過於繁瑣,動不動就是來個nginx,然后配置一堆參數和設置,尤其是做分布式的時候,那維護成本一下就上來了,從維護和部署的角度,FastDFS不是一個好的選擇,而從迭代的角度,FastDFS早就不維護了,有很多需求是無法
支持到的,那么就需要你自己思考寫源碼打包了。
同理HDFS部署也不簡單,而且Hadoop適合超大文件的存儲,並且文件都需要分片,應用場景更多是計算處理,實時數據分析,並且其實HDFS比較吃硬件設備,因為偏於計算,所以對CPU的要求比較高,對於中小企業的業務量並沒有這么大,所以應用場景這塊也比較
難接觸到,但是HDFS的功能還是十分強大的!!還是根據業務進行選型。
存儲方案的選型
以下選型方案,來自於探探
這是探探app的幾個功能,它的基礎功能非常簡單左划右划,左划是不喜歡,右划是喜歡,當兩個人相互喜歡就配對成功了,配對成功之后就開始相互聊天。
你所看到的一些圖片、視頻還有在聊天中產生的語音,這些元素在對象存儲的范疇里面,就是以對象保存下來。
隨着用戶量的增長,探探所要存儲的對象越來越多。
探探存儲的文件類型
這是探探2019年的文件存儲數據.
- 數據的體量為:
在不同類型對象所占的空間中,顯而易見圖片是存儲的一個大頭,超過了 1PB,它定期清理所以大小基本上保持了穩定的狀態。
- 訪問的吞吐量數據為:
寫入的 QPS 大概是 1 千左右,讀取是 5 千左右,壓力不是很大。
方案選型
於是,探探團隊就開始調研當前的一些開源方案,這些存儲方案里面可以分為兩種:
-
一種是可以自定對象名稱的;
-
另外一種是系統自動生成對象名稱。
探探的對象名是自己生成的,里面包含了業務邏輯。
像 FS 就是國內大佬開源的一個分支存儲,但是因為不能自定義文件名所以不合適,左划掉。
還有像領英的 Ambry、MogileFS 其實都不能自定對象名的,所以是不合適的。
左上角 LeoFS 對探探來說不是很可控,所以不合適。
TFS 是淘寶開源的,但是目前已經很少有人維護它並且也不是很活躍,所以當時就沒有考慮。
ceph 是一個比較強大的分布式存儲,但是它整個系統非常復雜需要大量的人力進行維護,和探探的產品不是很符合,所以暫時不考慮。
GlusterFS 為本身是一個非常成熟的對象存儲的方案。2011年左右被收購了,他們原版人馬又做了另外一個存儲系統MINIO,仙鶴就是他們的 logo。
MINIO 的文檔非常詳細、具體,再加上他們之前在存儲方面有十幾年的經驗,所以就這樣打動了探探團隊,作為選型的標的。
MinIO 介紹
Minio 是個基於 Golang 編寫的開源對象存儲套件,雖然輕量,卻擁有着不錯的性能。
官網地址:MinIO | High Performance, Kubernetes Native Object Storage
何為對象存儲?
對象存儲服務(Object Storage Service,OSS)是一種海量、安全、低成本、高可靠的雲存儲服務,適合存放任意類型的文件。容量和處理能力彈性擴展,多種存儲類型供選擇,全面優化存儲成本。
MinIO 是一個基於Apache License v2.0開源協議的對象存儲服務。
它兼容亞馬遜S3雲存儲服務接口,非常適合於存儲大容量非結構化的數據,例如圖片、視頻、日志文件、備份數據和容器/虛擬機鏡像等,而一個對象文件可以是任意大小,從幾kb到最大5T不等。
MinIO是一個非常輕量的服務,可以很簡單的和其他應用的結合,類似 NodeJS, Redis 或者 MySQL。
對於中小型企業,如果不選擇存儲上雲,那么 Minio 是個不錯的選擇,麻雀雖小,五臟俱全。
當然 Minio 除了直接作為對象存儲使用,還可以作為雲上對象存儲服務的網關層,無縫對接到 Amazon S3、MicroSoft Azure。
MINIO 基礎概念
MINIO 有幾個概念比較重要:
-
Object:存儲到 Minio 的基本對象,如文件、字節流,Anything...
-
Bucket:用來存儲 Object 的邏輯空間。每個 Bucket 之間的數據是相互隔離的。對於客戶端而言,就相當於一個存放文件的頂層文件夾。
-
Drive:即存儲數據的磁盤,在 MinIO 啟動時,以參數的方式傳入。Minio 中所有的對象數據都會存儲在 Drive 里。
-
Set
即一組 Drive 的集合,分布式部署根據集群規模自動划分一個或多個 Set ,每個 Set 中的 Drive 分布在不同位置。一個對象存儲在一個 Set 上。(For example: {1...64} is divided into 4 sets each of size 16.)
- 一個對象存儲在一個Set上
- 一個集群划分為多個Set
- 一個Set包含的Drive數量是固定的,默認由系統根據集群規模自動計算得出
- 一個SET中的Drive盡可能分布在不同的節點上
Set /Drive 的關系
Set /Drive 這兩個概念是 MINIO 里面最重要的兩個概念,一個對象最終是存儲在 Set 上面的。
我們來看下邊 MINIO 集群存儲示意圖,每一行是一個節點機器,這有 32 個節點,每個節點里有一個小方塊我們稱之 Drive,Drive 可以簡單地理解為一個硬盤。
圖中,一個節點有 32 個 Drive,相當於 32 塊硬盤。
Set 是另外一個概念,Set 是一組 Drive 的集合,圖中,所有藍色、橙色背景的Drive(硬盤)的就組成了一個 Set.
MIINO如何寫入對象?
MINIO 是通過數據編碼,將原來的數據編碼成 N 份,N 就是一個 Set 上面 Drive 的數量,后面多次提到的 N 都是指這個意思。
上圖中,一個 Set 上面 Drive 的數量,是3.
對象被編碼成N份之后,把每一份,寫到對應的 Drive 上面,這就是把一個對象存儲在整個 Set 上。
一個集群包含多個 Set,每個對象最終存儲在哪個 Set 上是根據對象的名稱進行哈希,然后影射到唯一的 Set 上面,這個方式從理論上保證數據可以均勻的分布到所有的 Set 上。
根據的觀測,數據分布的也非常均勻,一個 Set 上包含多少個 Drive 是由系統自動根據集群規模算出來的,當然,也可以自己去配置。
一個 Set 的 Drive 系統會考慮盡可能把它放在多的節點上面,保證它的可靠性。
Minio存儲架構
Minio針對不同應用場景也設置了對應的存儲架構:
單主機,單硬盤模式
該模式下,Minio只在一台服務器上搭建服務,且數據都存在單塊磁盤上,該模式存在單點風險,主要用作開發、測試等使用
啟動的命令為:
minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1
單主機,多硬盤模式
該模式下,Minio在一台服務器上搭建服務,但數據分散在多塊(大於4塊)磁盤上,提供了數據上的安全保障
minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1 /disk2/data/tenant1 /disk3/data/tenant1 /disk4/data/enant1
多主機、多硬盤模式(分布式)
該模式是Minio服務最常用的架構,通過共享一個access_key和secret_key,在多台(2-32)服務器上搭建服務,且數據分散在多塊(大於4塊,無上限)磁盤上,提供了較為強大的數據冗余機制(Reed-Solomon糾刪碼)。
export MINIO_ACCESS_KEY=<TENANT1_ACCESS_KEY>
export MINIO_SECRET_KEY=<TENANT1_SECRET_KEY>
minio --config-dir ~/tenant1 server --address :9001 http://192.168.10.11/data/tenant1 http://192.168.10.12/data/tenant1 http://192.168.10.13/data/tenant1 http://192.168.10.14/data/tenant1
分布式Minio有什么好處?
在大數據領域,通常的設計理念都是無中心和分布式。Minio分布式模式可以幫助你搭建一個高可用的對象存儲服務,你可以使用這些存儲設備,而不用考慮其真實物理位置。
數據保護
分布式Minio采用 糾刪碼來防范多個節點宕機和位衰減bit rot
。
分布式Minio至少需要4個硬盤,使用分布式Minio自動引入了糾刪碼功能。
高可用
單機Minio服務存在單點故障,相反,如果是一個有N塊硬盤的分布式Minio, 只要有N/2硬盤在線,你的數據就是安全的。
不過你需要至少有N/2+1個硬盤來創建新的對象。
例如,一個16節點的Minio集群,每個節點16塊硬盤,就算8台服務器宕機,這個集群仍然是可讀的,不過你需要9台服務器才能寫數據。
注意,只要遵守分布式Minio的限制,你可以組合不同的節點和每個節點幾塊硬盤。
比如,你可以使用2個節點,每個節點4塊硬盤,也可以使用4個節點,每個節點兩塊硬盤,諸如此類。
一致性
Minio在分布式和單機模式下,所有讀寫操作都嚴格遵守read-after-write一致性模型。
MinIO的數據高可靠
Minio使用了Erasure Code 糾刪碼和 Bit Rot Protection 數據腐化保護這兩個特性,所以MinIO的數據可靠性做的高。
Erasure Code糾刪碼
糾刪碼(Erasure Code)簡稱EC,是一種數據保護方法,它將數據分割成片段,把冗余數據塊擴展、編碼,並將其存儲在不同的位置,比如磁盤、存儲節點或者其它地理位置。
從數據函數角度來說,糾刪碼提供的保護可以用下面這個簡單的公式來表示:n = k + m。變量“k”代表原始數據或符號的值。變量“m”代表故障后添加的提供保護的額外或冗余符號的值。變量“n”代表糾刪碼過程后創建的符號的總值。
舉個例子,假設n=16,代表有16塊磁盤,另外,有10份原始文件一模一樣,稱為k,16 = 10 +m,這個m就是可以恢復的校驗塊個數,所以m是6,任意6個不可用,原始文件都可以恢復,極端情況,10個原始文件壞掉6個,靠4個原始的加上6個校驗塊,可以把壞掉的6個原始文件恢復,這個用到數學行列式矩陣知識,不做展開。
MinIO的編碼方式,將一個對象編碼成若干個數據塊和校驗塊,我們簡稱為Erasure Code碼,這個是編碼的類型,這種編碼的類型,還需要算法來實現,minio 采用的是 Reed-Solomon算法。
MinIO使用Reed-Solomon算法,該算法把對象編碼成若干個數據塊和校驗塊。
Reed-Solomon算法的特點:
- 低冗余
- 高可靠
為了表述方便,把數據塊和校驗塊統稱為編碼塊,之后我們可以通過編碼塊的一部分就能還原出整個對象。
Reed-Solomon code
Reed-Solomon 是糾刪碼的實現算法的一種,當然,也是一種恢復丟失和損壞數據的數學算法,
Minio默認采用Reed-Solomon code將數據拆分成N/2個數據塊和N/2個奇偶校驗塊。
這就意味着如果是16塊盤,一個對象會被分成8個數據塊、8個奇偶校驗塊,你可以丟失任意8塊盤(不管其是存放的數據塊還是校驗塊),你仍可以從剩下的盤中的數據進行恢復。
如上圖,如我們所知,一個對象存儲在一個Set上面,這個Set包含16個Drive,其中灰色的一半是數據庫,橙色的一半是校驗塊,這種方式最多能忍受一半的編碼丟失或損壞。
所有編碼塊的大小是原對象的2倍,跟傳統多副本存儲方案相比,他只冗余存了一份,但可靠性更高。
糾刪碼的工作原理和RAID或者副本不同,像RAID6只能在損失兩塊盤,或者以下的情況下不丟數據,而Minio糾刪碼可以在丟失一半的盤的情況下,仍可以保證數據安全。
而且Minio糾刪碼是作用在對象級別,可以一次恢復一個對象,而RAID是作用在卷級別,數據恢復時間很長。
Minio對每個對象單獨編碼,存儲服務一經部署,通常情況下是不需要更換硬盤或者修復。
此外,針對不同應用所需的數據安全級別不同,Minio還提供了存儲級別(Storage Class)的配置,調整數據塊和校驗塊的比例,做到對空間的最佳使用。
比如在將比例調整為14:2后,存儲100M的數據占用的空間僅為114M。
Bit Rot Protection:
接下來講Bit Rot Protection,直譯就是腐爛。
它只是物理設備上的一些文件細微的損壞,還沒有被操作系統所硬件所察覺,但是他已經損壞了。
Bit Rot 位衰減又被稱為數據腐化Data Rot、無聲數據損壞Silent Data Corruption,
位衰減可以理解為無形中的數據丟失——或者稱為“Bit rot”, 是指物理存儲介質的衰減所帶來的隱患將凸顯出來。
位衰減是目前硬盤數據的一種嚴重數據丟失問題。
硬盤上的數據可能會神不知鬼不覺就損壞了,也沒有什么錯誤日志。
一項對150萬塊硬盤的研究表明,每90塊硬盤就有1塊有這種“軟錯誤”,這個錯誤不但會導致數據丟失,還會導致RAID錯誤。
針對這一問題,最新的Minio采用了HighwayHash算法計算校驗和來防范位衰減,根據測試結果,其可以實現10GB/s的處理速度。
大致的做法是:
MinIO把之前的編碼塊進行 HighwayHash 編碼,最后要校驗這個編碼,以確保每個編碼是正確的。
文件的修復
另外,MinIO提供了一個管理工具,可以對所有編碼塊進行校驗,如果發現編碼塊有問題,再去修復它。
得益於Reed-Solomon糾刪碼,Minio可以更加靈活的對文件進行修復。
目前,Minio提供了全量、bucket、文件夾、文件等各個粒度的修復操作:
遞歸修復
$ mc admin heal -r myminio
指定桶修復
$ mc admin heal -r myminio/dev
下面是幾個例子:
相比一般的RAID方式,Minio可以在非常小的粒度下對文件進行修復操作,靈活性有了很大提高。
修復后,可以JSON格式列出指定路徑(文件、大小)
$ mc ls -r --json myminio/dev
{
"status": "success",
"type": "file",
"lastModified": "2019-05-30T09:43:07.763-04:00",
"size": 44996289,
"key": "myFile",
"etag": "bae58dc18zzzzz54c14e233b520e0a"
}
部署實操
Minio 提供了兩種部署方式:
- 單機部署
- 分布式
兩種部署方式都非常簡單,其中分布式部署還提供了糾刪碼功能來降低數據丟失的風險。
單機部署:
minio server /data
分布式部署:
export MINIO_ACCESS_KEY=<ACCESS_KEY>
export MINIO_SECRET_KEY=<SECRET_KEY>
minio server http://host{1...n}/export{1...m} http://host{1...o}/export{1...m}
Docker Compose部署
官方的文檔:
https://docs.min.io/cn/deploy-minio-on-docker-compose.html
Docker Compose允許定義和運行單主機,多容器Docker應用程序。
使用Compose,您可以使用Compose文件來配置MinIO服務。 然后,使用單個命令,您可以通過你的配置創建並啟動所有分布式MinIO實例。 分布式MinIO實例將部署在同一主機上的多個容器中。 這是建立基於分布式MinIO的開發,測試和分期環境的好方法。
環境說明
操作系統 | ip地址 | docker版本 | Docker Compose版本 |
---|---|---|---|
centos 7.6 | 192.168.31.34 | 19.03.8 | 1.24.1 |
運行分布式MinIO
在Docker Compose上部署分布式MinIO,請下載docker-compose.yaml到你的當前工作目錄。Docker Compose會pull MinIO Docker Image,所以你不需要手動去下載MinIO binary。然后運行下面的命令
docker-compose pull
docker-compose up -d
現在每個實例都可以訪問,端口從9001到9004,請在瀏覽器中訪問http://127.0.0.1:9001/
注意事項
-
默認情況下Docker Compose file使用的是最新版的MinIO server的Docker鏡像,你可以修改image tag來拉取指定版本的MinIO Docker image.
-
默認情況下會創建4個minio實例,你可以添加更多的MinIO服務(最多總共16個)到你的MinIO Comose deployment。添加一個服務
- 復制服務定義並適當地更改新服務的名稱。
- 更新每個服務中的命令部分。
- 更新要為新服務公開的端口號。 另外,請確保分配給新服務的端口尚未使用。
關於分布式MinIO的更多資料,請訪問這里.
-
Docker compose file中的MinIO服務使用的端口是9001到9004,這允許多個服務在主機上運行。
訪問MinIO
http://192.168.31.34:9001/minio/
用戶名:minio,密碼:minio123
登錄之后,效果如下:
MinIO操作
修改密碼
點擊右上角
提示:無法通過瀏覽器更新此用戶的憑據
注意:如果需要修改密碼,修改docker-compose.yaml中的MINIO_ACCESS_KEY和MINIO_SECRET_KEY變量即可。
創建bucket(文件夾)
先來創建一個bucket
創建data
上傳文件
選中data,點擊右下角的上傳文件
選擇一張圖片,上傳成功之后,效果如下:
查看bucket文件信息
點擊data,查看與設置該Object的基本信息:
查看共享地址Shareable Link
設置到期時間,最大可保存時間為7天
對話框上方彈出該Object現剩余到期時間
附錄1:Minio糾刪碼的補充學習
Minio使用糾刪碼erasure code
和校驗和checksum
來保護數據免受硬件故障和無聲數據損壞。 即便您丟失一半數量(N/2)的硬盤,您仍然可以恢復數據。
什么是糾刪碼erasure code
?
糾刪碼是一種恢復丟失和損壞數據的數學算法, Minio采用Reed-Solomon code 算法將對象拆分成N/2數據和N/2 奇偶校驗塊。 這就意味着如果是12塊盤,一個對象會被分成6個數據塊、6個奇偶校驗塊,你可以丟失任意6塊盤(不管其是存放的數據塊還是奇偶校驗塊),你仍可以從剩下的盤中的數據進行恢復,是不是很NB,感興趣的同學請FQgoogle。
為什么糾刪碼有用?
糾刪碼的工作原理和RAID或者復制不同,像RAID6可以在損失兩塊盤的情況下不丟數據,而Minio糾刪碼可以在丟失一半的盤的情況下,仍可以保證數據安全。 而且Minio糾刪碼是作用在對象級別,可以一次恢復一個對象,而RAID是作用在卷級別,數據恢復時間很長。 Minio對每個對象單獨編碼,存儲服務一經部署,通常情況下是不需要更換硬盤或者修復。Minio糾刪碼的設計目標是為了性能和盡可能的使用硬件加速。
Minio糾刪碼實驗
1. 前提條件:
安裝Minio- Minio快速入門
2. 以糾刪碼模式運行Minio
示例: 使用Minio,在12個盤中啟動Minio服務。
minio server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8 /data9 /data10 /data11 /data12
示例: 使用Minio Docker鏡像,在8塊盤中啟動Minio服務。
docker run -p 9000:9000 --name minio \
-v /mnt/data1:/data1 \
-v /mnt/data2:/data2 \
-v /mnt/data3:/data3 \
-v /mnt/data4:/data4 \
-v /mnt/data5:/data5 \
-v /mnt/data6:/data6 \
-v /mnt/data7:/data7 \
-v /mnt/data8:/data8 \
minio/minio server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8
3. 驗證是否設置成功
你可以隨意拔掉硬盤,看Minio是否可以正常讀寫。
附錄2:什么是位衰減bit rot
保護?
位衰減又被稱為數據腐化Data Rot
、無聲數據損壞Silent Data Corruption
,是目前硬盤數據的一種嚴重數據丟失問題。
硬盤上的數據可能會神不知鬼不覺就損壞了,也沒有什么錯誤日志。
正所謂明槍易躲,暗箭難防,這種背地里犯的錯比硬盤直接咔咔宕了還危險。
不過不用怕,Minio糾刪碼采用了高速 HighwayHash 基於哈希的校驗和來防范位衰減。
附錄3:Springboot集成MinIO基礎實現
新建一個項目springboot-minio,主要代碼:
@RestController
@Slf4j
public class FileController {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucketName}")
private String bucketName;
@GetMapping("/list")
public List<Object> list() throws Exception {
//獲取bucket列表
Iterable<Result<Item>> myObjects = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
Iterator<Result<Item>> iterator = myObjects.iterator();
List<Object> items = new ArrayList<>();
String format = "{'fileName':'%s','fileSize':'%s'}";
while (iterator.hasNext()) {
Item item = iterator.next().get();
items.add(JSON.parse(String.format(format, item.objectName(),
formatFileSize(item.size()))));
}
return items;
}
@PostMapping("/upload")
public ResultBean upload(@RequestParam(name = "file", required = false)
MultipartFile[] file) {
ResultBean resultBean = ResultBean.newInstance();
if (file == null || file.length == 0) {
return resultBean.error("上傳文件不能為空");
}
List<String> orgfileNameList = new ArrayList<>(file.length);
for (MultipartFile multipartFile : file) {
String orgfileName = multipartFile.getOriginalFilename();
orgfileNameList.add(orgfileName);
try {
//文件上傳
InputStream in = multipartFile.getInputStream();
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(orgfileName).stream(
in, multipartFile.getSize(), -1)
.contentType(multipartFile.getContentType())
.build());
in.close();
} catch (Exception e) {
log.error(e.getMessage());
return resultBean.error("上傳失敗");
}
}
Map<String, Object> data = new HashMap<String, Object>();
data.put("bucketName", bucketName);
data.put("fileName", orgfileNameList);
return resultBean.ok("上傳成功", data);
}
@RequestMapping("/download/{fileName}")
public void download(HttpServletResponse response, @PathVariable("fileName")
String fileName) {
InputStream in = null;
try {
// 獲取對象信息
StatObjectResponse stat = minioClient.statObject(
StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
response.setContentType(stat.contentType());
response.setHeader("Content-Disposition", "attachment;filename=" +
URLEncoder.encode(fileName, "UTF-8"));
//文件下載
in = minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build());
IOUtils.copy(in, response.getOutputStream());
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
}
@DeleteMapping("/delete/{fileName}")
public ResultBean delete(@PathVariable("fileName") String fileName) {
ResultBean resultBean = ResultBean.newInstance();
try {
minioClient.removeObject(
RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
} catch (Exception e) {
log.error(e.getMessage());
return resultBean.error("刪除失敗");
}
return resultBean.ok("刪除成功", null);
}
private static String formatFileSize(long fileS) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
String wrongSize = "0B";
if (fileS == 0) {
return wrongSize;
}
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + " B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + " KB";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + " MB";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + " GB";
}
return fileSizeString;
}
}
yml配置
minio:
endpoint: http://10.12.105.15:9000
accesskey: minioadmin
secretKey: minioadmin
bucketName: chenxin-bucket
啟動Springboot項目后,調用localhost:8080/list
用postman上傳試下,很明顯上傳成功了。
同理下載也是一樣,看下接口就清楚了,接口后面跟着文件名就可以下載了,當然這個
后面要做成存儲到數據庫里,這個后面我拓展出來,先會使用再說。
參考代碼:https://gitee.com/cx_gitee/springboot-minio
參考文檔
https://www.jianshu.com/p/95538d262b93
http://tech.dianwoda.com/2018/12/04/fen-bu-shi-cun-chu-xi-tong-miniojian-jie/
https://www.jianshu.com/p/68ac0477291d
https://studygolang.com/articles/34762
http://docs.minio.org.cn/docs/master/distributed-minio-quickstart-guide
https://blog.csdn.net/qq_31821733/article/details/119882573
https://blog.51cto.com/zyrs/2749314
https://docs.min.io/cn/deploy-minio-on-docker-compose.html