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