相比微服务,模块化单体应用架构可能是更好的选择?

关注公众号!留言:参考模板 ,
送《技术方案设计参考模板》

1 引言

微服务架构风格由来已久,行业内已经进行了大量的工程实践。对于具备一定规模的系统,设计人员基于业务内聚性进行微服务化设计已经是一个普遍使用的方式。但微服务架构风格的“滥用”使得我们需要重新审视微服务架构风格在工程实践中是否是最优选择。

2 微服务架构风格的工程实践困境

典型的微服务架构风格如下:基于独立的业务域划分为不同的微服务单元,每个单元逻辑上或物理上独享数据库。各个微服务单元独立部署、独立伸缩。

图片

基于微服务架构风格的特性,其具有易伸缩、易扩展的特性。通过明确清晰的服务编辑,最大程度降低服务间的耦合。同时,微服务单元的技术栈可以异构,按照各自不同的诉求进行技术选型。

微服务具有明天的架构风格特性和优势,但在大量的工程实践中,其挑战主要来源于不合理的应用导致形成庞大的分布式单体和维护负担。在个人经历的平台系统中例子比比皆是,例如:

1.从 0 到 1 建设的私域电商系统开发初期即基于“微服务”划分了不同子系统,极大增加了系统复杂度和团队研发成本。

2.有些系统的体量不大,但子系统数量多个20~30个,研发成员只有5-6人,平均每人维护4+系统,可想认知成本和研发成本多高。

3.有些系统虽然划分了子系统,但其划分规则多基于“技术”视角,而非业务域视角,每个微服务并不是真正的业务闭环。随着系统迭代存在大量的调用依赖、高度耦合,形成庞大的分布式单体应用

3 温故知新

3.1 单体应用架构

单体应用架构也是使用比较普遍的应用架构,适用于小规模系统,典型的开发模式如下:

图片

传统单体应用架构的优势:

1. 开发简单:单一代码库:所有功能模块都集中在同一个代码库中,开发人员可以快速理解和修改代码。快速迭代:由于没有复杂的模块划分和通信机制,开发团队可以快速实现新功能并发布。

2. 部署简单:单一部署单元:整个应用作为一个整体部署,无需管理多个独立服务或容器。简化运维:部署和回滚过程简单,减少了运维的复杂性。

3. 性能高效:所有模块在同一个进程中运行,通信通过本地调用完成,避免了网络延迟和通信开销。资源利用率高:由于没有服务间的网络通信和额外的资源隔离层,资源利用更高效。

4. 调试和测试简单:集中式日志和监控:所有日志和监控数据集中在一个地方,便于排查问题。端到端测试:测试环境简单,可以轻松进行端到端测试,确保整个应用的功能一致性。

5. 成本低:基础设施成本低:无需为多个服务配置独立的服务器、数据库或容器,节省了硬件和云资源成本。开发成本低:开发团队无需掌握复杂的分布式系统设计和管理技能,降低了人力成本。

传统单体的局限性

1.紧密耦合:模块通常紧密耦合,难以独立开发和测试。

2.难以扩展:在需要扩展时,传统单体应用程序往往需要重构整个系统。

3.技术债务:传统单体应用程序容易积累技术债务,尤其是在模块边界不清晰的情况下。

3.2 模块化单体应用架构

模块化单体架构是一种将软件应用程序组织为一组模块的方式。每个模块高内聚、模块间低耦合,可以独立开发和测试,整个应用程序作为一个整体单元部署。

Examples of the 7 modules in a typical e-commerce application and how they can be independantly deployed when needed

从底层的工程视角看,模块单体应用内部基于“模块化”进行代码组织,例如Java元的Maven Module。每个模块具有清晰明确的边界,多数情况下这些边界基于业务边界进行划分。模块间的交互基于模块间的协议契约(API或消息)。

图片

模块化单体的优点

1.简化开发和测试:由于模块是独立的,开发和测试过程更加简化。

2.清晰的模块边界:每个模块都有明确的业务能力边界,减少了模块间的耦合。

3.易于部署:整个应用程序作为一个单元部署,减少了部署复杂性。

4.灵活性:可以根据需要提取和扩展特定模块,而无需重构整个应用程序。 模块之间的接口可以作为未来微服务之间的契约,支持独立部署和扩展。

5.易于迁移到微服务:由于模块的独立性,未来可以轻松地将模块转换为微服务。

模块化单体的挑战

1.模块边界管理:需要仔细管理模块之间的边界,以避免紧密耦合。

2.扩展限制:虽然可以提取模块进行扩展,但在大规模扩展时可能会遇到限制。

3.技术债务:如果不加以管理,模块化单体可能会积累技术债务。

3.3 模块化单体 vs 微服务架构 

模块化单体与传统单体的主要区别在于,模块化单体由定义明确、独立且可提取的模块组成,每个模块都拥有特定的业务能力边界。当模块的规模和复杂性增加,需要不同的资源和部署时,更容易迁移到微服务架构,因为:

1.从领域驱动设计的角度来看,它已经指定了微服务的理想边界。

2.每个模块未来都可以成为独立的微服务候选。

3.接口可以演变为独立部署的微服务之间的契约。

图片

4 应用架构选型的建议

原则上,优先考虑模块化单体架构是否可以满足当前诉求,避免一上来就进行复杂的微服务拆分。具体应该基于具体情况具体分析,不能一概而论。

例如,对于成熟的平台型系统,在明确的系统性能、吞吐量预估指标下,直接微服务化可能是最有选择。又例如,基于不同模块的伸缩性不同,拆分为独立的微服务系统也是合理选择。

根本上,应用架构选择是一种架构决策,需要设计人员进行权衡。

4.1 为什么要从模块化单体架构开始?

1. 初始阶段更少的复杂性

在任何项目的初期,团队仍在了解领域和更大的生态系统。如果项目一开始就采用微服务方法,随着团队理解的深入,已经构建的微服务将直接受到影响。

相比之下,模块化单体设计具有较少的复杂性,使得修改更容易和快速。一旦团队对业务领域及其边界上下文有了扎实的理解,他们可以迁移到微服务架构。

2. 更简单的创建、部署和管理

在微服务方法中,每个服务必须独立部署,这增加了技术和操作复杂性。此外,每个服务可能需要单独处理,这增加了DevOps团队的负担。

在模块化单体架构中,模块作为一个单元生产和交付,使得应用程序的设计、部署和管理显著简化。

3. 更好的功能和稳定性

微服务可能会因为服务之间网络流量的增加而遇到性能问题。随着复杂性的增加,微服务也可能更容易出现错误和缺陷。

模块化单体架构中的模块被设计为相互流畅地工作,从而提高了性能和稳定性。

4. 成本效益

微服务需要额外的基础设施,如API网关、负载均衡、服务发现等。这使得它比模块化单体架构更昂贵,尤其是在开发的早期阶段。

在模块化单体中,所有模块可以部署在单个服务器上,所需的基础设施较少,因此更具成本效益。

即使基于模块化单体架构,团队也必须时刻关注单体架构的腐化问题。与微服务类似,模块的职责边界以及依赖关系也要仔细慎重的评审,尽量避免模块间随意的、双向调用。否则,随着系统的迭代,模块间的耦合问题会给后续系统的可维护性带来较大挑战,同时,也不利于后续从模块化单体向微服务的架构迁移。

4.2 何时迁移到微服务?

1. 当可扩展性成为关键因素

如果不同的模块需要不同的扩展方式,微服务可能是更好的选择。通过微服务,可以更轻松地独立扩展单个服务,从而实现对应用程序的更精细控制。

2. 当团队规模扩大

如果开发团队规模较大,导致复杂性增加,是时候迁移到微服务了。通过微服务,每个服务可以独立开发和测试,从而促进团队之间更好的协作。

3. 当需要多样化的技术

如果应用程序的不同部分需要不同的技术/语言,微服务是理想的选择。通过微服务,每个服务可以使用自己的技术栈,从而在开发过程中提供更大的灵活性。

4. 当对复杂领域有了扎实的理解

当对领域及其多个子系统有了扎实的理解后,微服务架构可以帮助封装和管理复杂性。通过将系统分解为更小、更专业的服务,应用程序将更容易维护和演进。

将微服务视为最终目标而非起点是有益的。在软件开发的早期阶段,模块化单体架构将为未来定义明确的边界上下文奠定基础,同时有助于控制膨胀的用例服务数量。

因此,在决定跳转到微服务之前,我们建议领导者考虑应用程序的规模和复杂性、预计的用户流量以及可用的技能资源。如果微服务看起来是一个巨大的跨越,模块化单体可能是你需要的跳板。

5 结语

虽然微服务架构风格有其独特优势,但前提是合理架构、划分业务单元。完全无脑的进行微服务化、拆分成庞大的子系统有时并不是一个好的选择,特别是针对初期项目,基于模块化单体应用架构可能是更好的选择。通过系统的不断迭代,随着上下文变化逐渐演进,是一个建议的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值