基于MinI0分布式存储的微服务模块开发应用
2023-12-04邱宇
摘要:文件存储是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 AggregateRoot
{
public long FileSize { get; set; }
public string MimeType { get; set; }
//省略类构造代码….
}
public class DocumentAppService : MinioAppService
{
//省略代码….
//文件上传服务
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. 旧文件迁移方案
之前系统使用Blob Storing File System接口直接存储在学校网络中心的NAS上,改用MinIO独立存储系统、使用Blob Storing MinIO接口后,需要将原来存储NAS上的文件分类转储到MinIO系统上,得益于新旧存储都使用BlobStoring类接口,文件都以GUID作为标识,因此可以编制专用迁移程序用于转储文件,该迁移程序主要代码如下。
public class FileMigrationService:MinioAppService
{
public async Task> 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.
作者简介:邱宇,硕士研究生,讲师,研究方向:计算机网络、计算机软件。