

摘要:文件存儲是OA(辦公自動化)系統中基礎的業務需求,過往OA系統將文件存儲在服務器本地硬盤或者NAS系統中,這種存儲方案隨著文件數量的增加,文件檢索和讀取速度會出現下降。對象存儲系統可以很好解決這個問題。本文描述基于一種開源的對象存儲系統MinIO構建的OA存儲模塊,該模塊以微服務形式交付應用。
關鍵詞:存儲模塊;MinIO;微服務
1. 微服務
微服務是信息系統開發過程中,為應對復雜場景和大規模部署而發展起來的軟件架構技術。核心思路是將業務系統按功能進行重構并將其拆分,最終得到可獨立部署運維、功能單一的模塊。微服務部署之后,通過微服務網關、事件總線統一協調,可以實現多個微服務相互通信和協同,共同完成IT系統的整體功能[1]。
與傳統架構體系相比,微服務具有易維護、易擴展、實用性強等特點。微服務通常在開發完畢后,以獨立docker鏡像發布,可在K8s等大規模編排系統的協調下快速部署和撤銷。在學校常規應用中最明顯的如選課服務,選課服務在每學期末最后一個星期開放,期間學校大量學生同時登錄使用該服務,在以往單體架構中,教務管理通常是校園辦公系統的一個功能模塊,或是另外一個獨立的單體系統,系統擴展性差,很難根據需要調度計算資源應對短期的高峰服務需求,經常出現系統過載、響應緩慢甚至系統崩潰的現象。采用微服務架構后,選課服務(系統)可以從龐大的教務系統中剝離出來,成為獨立的服務系統,通過K8s統一調度,在選課前可以快速部署多個選課微服務以應對大量的并發。選課結束后,可以迅速注銷這些微服務,騰出學校的計算資源。部分高校如果日常不具備多余計算資源部署選課微服務,得益于微服務架構靈活性,這些選課微服務可以臨時部署到諸如阿里云、華為云等公有云上,這些云服務商都支持計時計量收費,用完即止,學校可以用較低成本按需擴張整套系統的服務能力。
2. 對象存儲
傳統文件存儲系統,如各類操作系統的文件系統、NAS系統等,在存儲文件過程中,只能附加常規元數據(如創建日期、文件大小等),隨著存儲數量的上升,這種簡單的存儲結構會出現檢索、存取速度下降的問題。不同于傳統文件存儲系統,對象存儲系統是數據存儲,每個數據單元(對象)都被視作離散單元,與數據單元有關的默認或者自定義元數據一起存儲在具有唯一標識的平面存儲空間中。這種存儲方式改變了傳統存儲系統嵌套分層結構,在提供更多元數據標記手段的基礎上,簡化了存儲結構,從而達到快速檢索、快速存取的目的。學校OA系統日常使用過程中,會產生大量無關聯的文本(Word/Excel/PDF)、圖片(拍攝、掃描等手段產生的)、教學音視頻資源等,對象存儲系統的非結構化存儲正好應對此類應用場景。
對象存儲系統通常具有很高的伸縮性和可靠性,可以依據存儲需求,在業務系統無感知狀態下快速靈活擴容(存儲對業務系統透明),可以很好地解決過往直接存儲在NAS系統或者本地磁盤陣列系統導致的性能慢、可靠性不高、難以擴展的弊端。
MinIO[2]是一款開源分布式對象存儲產品,面對應用,可以作為存儲服務為學校OA應用提供統一的文件管理功能,支持不同存儲需求創建獨立的存儲桶,實現安全隔離的同時又可以相互共享。MinIO除支持單機部署,也提供基本集群部署功能,方便實現異地分布式部署。多個部署節點共同組成存儲系統,通過統一的訪問接口存儲數據。MinIO使用糾錯碼機制來保障所存儲資源的完整性,防止節點故障導致信息滅失,其設計具備高度的可用性和可靠性。整套存儲系統只要有一半節點狀態正常,就能保證數據正常讀取,只要超過一半節點正常,就能保證數據正常寫入。故障節點恢復方便,而且支持熱機在線操作,不會對正在執行的讀取存儲業務產生任何干擾。
MinIO兼容亞馬遜S3云存儲服務接口規范,使原本使用亞馬遜云存儲的應用系統無須修改代碼即可切換到MinIO,或者混合使用MinIO和亞馬遜公有云存儲,比如應用系統當中高可靠性要求的內容存儲在亞馬遜云,其他內容或者私密性高的內容存儲在學校MinIO系統。
雖然MinIO可以很好兼容S3存儲接口,但其誕生之初是針對私有存儲云設計的,提供對象存儲系統的核心功能,放棄了復雜大規模集群調度管理等私有云少用的功能,從而使得系統更加輕量化,更加適合學校或企業等中小規模實體內部部署和運維。
3. 系統架構
學校整套OA系統基于微服務架構設計,提供用戶身份認證和訪問鑒權、辦公OA、教務管理、學生管理等業務模塊,每個業務模塊都基于一個組微服務實現,如圖1所示。在這些微服務和終端用戶之間提供API網關(微服務網關),微服務網關成為系統暴露在外部的唯一應用訪問入口,是所有外部客戶端訪問各個微服務的中轉中心,處理非業務功能,僅提供尋址、準入檢驗、服務位置引導等功能。
Ocelot是一款基于.NetCore實現的API網關,目前在GitHub平臺上開源,提供包括路由、請求聚合、服務發現、認證、鑒權等功能,配置簡單、功能齊全、性能卓越,是基于.NetCore開發的微服務系統廣泛使用的網關。
按微服務設計規范,身份認證和鑒權由微服務網關Ocelot承擔,所有外部訪問都在路由API之前完成認證和鑒權,基于學校管理需要,身份認證和鑒權服務并未托管在Ocelot中,而是在后端提供身份認證和鑒權微服務,Ocelot轉調位于后端的身份認證和鑒權微服務。另外,根據多年實踐,學校在選課期間,登錄鑒權的訪問請求會暴增,需要動態擴展身份認證和鑒權微服務。將此服務從Ocelot分離,是多年實踐的結果,能進一步保障系統彈性。
本次開發的MinIO存儲業務微服務(圖1實線框所示),是要解決整套系統大量文本、視頻文件存儲的需要。之前系統使用BlobStoringFileSystem接口直接存儲在學校網絡中心的NAS上,隨著文件數量的增加,出現了性能瓶頸問題。
4. 存儲業務模塊開發實現
4.1 開發框架選型
ABP.VNext[3]是開源社區提供的一款基于.NetCore的快速開發框架,提供了現代化應用軟件系統所使用的各類基礎設施模塊,如數據存儲、消息發送、自動WebAPI構建、動態代理等,預置齊全的各類基礎設施模塊,開發團隊可以方便集成使用,無須在各種應用系統開發中重復構建它們。通用模塊化集成能力,讓開發者將精力集中在業務設計和實現方面,提高軟件開發過程的生產效率。
在領域驅動設計(domain driven design-DDD)建議的分層原則中,組件(class)只能依賴于本層的其他組件,或向下依賴其他層的組件。分層的主要目的是分離關注點,每個層次職責劃分非常清晰,開發團隊可以構建通用的基礎設施層(模塊),這樣團隊便可以更專注于領域模型的設計和構建。所創建的系統具有高內聚、低耦合的特征,長期而言可以降低系統的維護成本,延長系統的生命周期。ABP.VNext框架也是遵循DDD模式的框架系統,提供了DDD建議的架構分層結構,有利于降低系統整體復雜性,使得開發團隊能夠聚焦于各層次的核心任務。功能分層也提高了框架的復用性。
ABP.VNext將工程分為以下五個核心層:
(1)表現層(presentation):是一套基于Web的應用界面程序,用于展現系統的功能。
(2)WebAPI層:用于對外提供HttpAPI接口,提供獨立的展現層,比如基于Vue框架實現的展現層。
(3)應用層(application):為WebAPI層和展現層提供應用服務。展現層和WebAPI層通過DTO(data transfer object)作為參數調用應用層的方法。
(4)領域層(domain):本層放置實體(entity)等項目最核心的代碼,用于實現項目所要處理的業務邏輯。ABP.VNext通過倉儲模式(repository)來讀寫數據,倉儲接口也在領域層聲明。
(5)基礎設施層(infrastructure):基礎設施層提供具體數據存取、緩存等應用域外通信功能。領域層定義了倉儲接口,倉儲的具體實現就在基礎設施層。
ABP框架從4.X版本開始,強化其微服務開發模式的支持,利用其本身的模塊化特征,可以輕松將大應用拆分成獨立的模塊,每個模塊都可以擁有自己的數據庫、實體和服務,可以自動產生REST風格的API,并對外發布。ABP框架提供了與微服務兼容的模塊架構,在這個架構中,開發者被分割成多個層甚至是多個項目,各個層或項目完全獨立,這種方式是天然的微服務架構,所開發的模塊可以很容易插入其他單體應用程序中,也可以攜帶REST API獨立部署,模塊之間通過調用API完成協調,各個模塊可以自帶工作數據庫,也可以共用數據庫,工作模式的切換只需簡單修改JSON格式的配置文件即可完成。
ABP.VNext除了提供完整可重復使用的模塊,還提供現成模板項目,免費版本的項目本身已經集成數據訪問、日志系統、用戶身份管理、權限管理、身份認證和鑒權、自動API和一套基本的前端UI模板,開發者可以按需集成ABP.VNext提供的其他模塊,并將其作為應用程序開發的起點,根據業務需求,持續開發。商業版本對比免費版提供更多的業務模塊,本文介紹的模塊基于開源版本進行開發。
4.2 創建應用程序
4.2.1 創建應用程序初始框架:
使用ABP.Vnext提供的腳手架—abp指令,創建出項目的初始框架:
abp new hzc.MinIO -t module
整個解決方案包含主要工程項目作用如表1所示。
4.2.2 具體實現項目
在Domain層創建一個存儲容器類,用于在標記MinIO存儲所屬類型。
接下來,在領域層(Domain)定義實體類型,用于標識文件實體。
//定義文件容器類型
[BlobContainerName(\"document\")]
public class DocumentContainer
{
}
//定義文件實體類
public class Document : FullAudited AggregateRootlt;Guidgt;
{
public long FileSize { get; set; }
public string MimeType { get; set; }
//省略類構造代碼….
}
public class DocumentAppService : MinioAppService
{
//省略代碼….
//文件上傳服務
public async Tasklt;DocumentDtogt; UploadAsync(Guid id,[FromForm] IFormFile file)
{
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream).ConfigureAwait(1);
var newFile = new Document(id, file.Length, file.ContentType);
await _blobContainer.SaveAsync(id.ToString(),
memoryStream.ToArray())
.ConfigureAwait(1);
return ObjectMapper.Maplt;Document, DocumentDtogt;(newFile);
}
}
5. 舊文件遷移方案
之前系統使用Blob Storing File System接口直接存儲在學校網絡中心的NAS上,改用MinIO獨立存儲系統、使用Blob Storing MinIO接口后,需要將原來存儲NAS上的文件分類轉儲到MinIO系統上,得益于新舊存儲都使用BlobStoring類接口,文件都以GUID作為標識,因此可以編制專用遷移程序用于轉儲文件,該遷移程序主要代碼如下。
public class FileMigrationService:MinioAppService
{
public async Tasklt;Listlt;FileDtogt;gt; GetListAsync()
{
//讀取需轉存文件信息
var list = await _FileRep.GetListAsync();
//存儲初始狀態,SaveStatusAsync方法重載
//它自動對比現有數據和新數據狀態,返回合適的需存儲列表
var listStore = await _MigrationFileRep.SaveStatusAsync(list);
foreach(var item in listStore){
if(item.Uploaded==true) return;
await _docService.UploadAsync(item.Id,item.Content);
item.Uploaded=true;//標識某文件已經轉存
await _MigrationFileRep.SaveStatus Async(item);//存儲新狀態
}
}
}
結語
本文通過MinIO對象存儲系統構建文件存儲微服務模塊,解決了原有文件存儲性能低下的問題。MinIO提供了高性能、高可靠的對象存儲能力,可以輕松擴展存儲容量,適應文件存儲量的增長。微服務架構使存儲模塊可以獨立部署,系統可以按需彈性擴展存儲服務能力。
ABP框架為快速開發微服務應用提供了模塊化的項目結構和預制的基礎設施組件。使用ABP可以快速構建存儲微服務模塊并集成到現有系統中,通過微服務網關統一接入。本文介紹的開發方式,可以使開發團隊更專注于業務設計,提高開發效率。
通過微服務和對象存儲技術的引入,文件存儲性能得到顯著提升,存儲容量可以輕松擴展,更好地滿足未來存儲量增長的需求。本文的開發方式可推廣應用到類似場景,幫助開發團隊快速高效地構建存儲類微服務。
參考文獻:
[1]孫吳昊,張國妍,蔣文杰,等.視聽媒體領域微服務架構中API網關的設計與驗證[J].廣播電視信息,2022,29(10):30-35.
[2]李兵,王連忠,司運成.MinIO存儲在監拍系統中的應用設計[J].工業控制計算機,2020,33(9):79-80,82.
[3]嚴海濤,袁琳,紀芳,等.設計接口管理系統架構搭建技術應用研究[J].科技資訊,2020,18(26):24-27.
作者簡介:邱宇,碩士研究生,講師,研究方向:計算機網絡、計算機軟件。