分散式文件存儲庫MinIO可還行?
在傳統的單體應用架構中,一個應用程式對應一台伺服器,提供單進程服務。
但是隨著業務的升級,技術的更新迭代,分散式、集群架構、微服務等現已儼然成為主流。
幾乎所有的項目都會與文件掛鉤,例如OA系統的報表文件,電商系統的商品圖片等等…
我們來看一下傳統的(單體應用)文件存儲與讀取方式
一台主機對於N個客戶端,如果是小項目還好,稍微大點的項目,伺服器分分鐘崩潰
進而演進為分散式架構
將每一個大的模組進行拆分,以前單進程支撐的系統現在多進程協同。將文件操作也進行剝離,部署到不同的伺服器進行維護,各司其職,減輕不同模組伺服器的壓力.
話又說回來了,怎樣實現呢?
這裡的話我主要說一下分散式文件的存儲服務MinIO。當然還有其他的一些中間件及工具,大家隨意即可。
首先介紹一下MinIO,MinIO是一款高性能的對象資源存儲庫,而且自身很輕量。
GitHub上start數已經有20多K了
https://github.com/minio
而且MinIO支援多種語言,也提供了豐富的API.
OK!現在要動手了。
用它肯定要先安裝它,我本次操作在Linux下。
首先在Docker中拉取一個鏡像並運行
docker pull minio/minio docker run -p 9000:9000 minio/minio server /data
它會分配給你密鑰,用作登錄。這個密鑰在後續項目中也會用到。
在瀏覽器中輸入ip:port如果正常顯示,就證明你安裝成功了。如下:
我們可以點擊加號,創建一個桶(文件夾)
注意文件夾的名稱不能大寫
我們可以上傳一張圖片
找到它的鏈接就可以在瀏覽器中訪問了
接下來在程式碼中進行CRUD了😅
先在項目中引入Minio包
PM> Install-Package Minio
我的是webapi的項目,你可隨意
上傳文件:
/// <summary> /// 上傳文件 /// </summary> /// <param name="file"></param> /// <returns></returns> [HttpPost] public async Task<IActionResult> Upload(IFormFile file) { try { var minio = new MinioClient(_configuration["Minio:endpoint"], _configuration["Minio:accessKey"], _configuration["Minio:secretKey"]); var data = await FileUpload.Run(minio, file); return new JsonResult(new { success = true, fileUrl = data.fileUrl, message = data.message }); } catch (Exception ex) { return new JsonResult(new { success = false, fileUrl = default(string), message = ex.Message }); } }
public async static Task<FileData> Run(MinioClient minio, IFormFile formFile) { var bucketName = "picfile"; var location = "us-east-1"; var objectName = $"pic/{DateTime.Now.ToString("yyyy-MM-dd")}/" + Guid.NewGuid().ToString().Replace("-", string.Empty); var contentType = "image/jpeg"; try { //判斷桶(文件夾)是否存在 bool found = await minio.BucketExistsAsync(bucketName); if (!found) { //新增桶(文件夾) await minio.MakeBucketAsync(bucketName, location); } //文件大小 var len = formFile.Length; //打開請求流以讀取上載的文件 var stream = formFile.OpenReadStream(); //上傳文件到桶(文件夾). await minio.PutObjectAsync(bucketName, objectName, stream, len, contentType, null, null); //返回url var url = await minio.PresignedGetObjectAsync(bucketName, objectName, 3600 * 24 * 7); //var data = await minio.StatObjectAsync("picfile", objectName); //... 對資料庫進行操作,例如存入文件名與桶(文件夾)的名稱 return new FileData { success = true, fileUrl = url, message = "上傳成功" }; } catch (MinioException ex) { return new FileData { success = false, fileUrl = default(string), message = ex.Message }; } }
密鑰和ip這些配置項我們可以寫在appsettings.json中
在控制器中已注入的形式使用
下載文件:
/// <summary> /// 下載文件 /// </summary> /// <param name="bucketName">桶(文件夾)名稱</param> /// <param name="objextName">文件名稱</param> /// <returns></returns> [HttpGet] public async Task<IActionResult> DownLoadFile(string bucketName, string objextName) { try { if (string.IsNullOrEmpty(bucketName) && string.IsNullOrEmpty(objextName)) return new JsonResult(new { message = "桶(文件夾)名稱和文件名稱不能為空!" }); //實例化minio客戶端 var minio = new MinioClient(_configuration["Minio:endpoint"], _configuration["Minio:accessKey"], _configuration["Minio:secretKey"]); //獲得圖片的鏈接 var url = await minio.PresignedGetObjectAsync("picfile", objextName, 3600 * 24 * 7); //實例化WebClient 對象 var webClient = new WebClient(); //根據圖片鏈接轉成byte位元組數組 var dataByte = webClient.DownloadData(url); return File(dataByte, "image/jpeg"); } catch (Exception ex) { return new JsonResult(new { message = ex.Message, success = false }); } }
移除文件:
/// <summary> /// 移除文件 /// </summary> /// <param name="bucketName"></param> /// <param name="objextName"></param> /// <returns></returns> [HttpDelete] public async Task<IActionResult> DeleteFile(string bucketName, string objextName) { try { if (string.IsNullOrEmpty(bucketName) && string.IsNullOrEmpty(objextName)) return new JsonResult(new { message = "桶(文件夾)名稱和文件名稱不能為空!" }); //實例化minio客戶端 var minio = new MinioClient(_configuration["Minio:endpoint"], _configuration["Minio:accessKey"], _configuration["Minio:secretKey"]); //移除文件 await minio.RemoveObjectAsync(bucketName, objextName); return new JsonResult(new { message = "移除資源文件成功", success = true }); } catch (Exception ex) { return new JsonResult(new { message = ex.Message, success = false }); } }
這裡的話只列舉以上幾個較常用的api,MinIO其實還提供了很多api,大家可以慢慢研究。
到此MinIO就介紹完了,大家可以根據自己需要在進行擴展。
中文官網:http://docs.minio.org.cn