Modular Monolith 模块化单体架构学习与实践指南(awesome-software-architecture 精选资源深度解读)
Modular Monolith 模块化单体架构学习与实践指南awesome-software-architecture 精选资源深度解读【免费下载链接】awesome-software-architecture A curated list of awesome articles, videos, and other resources to learn and practice software architecture, patterns, and principles.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-software-architecture导读模块化单体Modular Monolith是一种试图同时吸收单体与微服务两种架构优点的折中方案它以单一代码库、单一部署单元与单一数据库交付系统却在内部以清晰的模块边界、明确的职责与接口进行组织从而保留团队独立开发、独立测试的能力并保留后续向微服务演进的路径。本篇指南以 awesome-software-architecture 仓库中 docs/modular-monolith.md 的精选资源为骨架结合仓库内 DDD、事件驱动、Outbox、反模式等配套文档系统讲解模块化单体的定义、架构驱动因素、模块边界划分、模块间通信、架构强制手段以及向微服务演进的路线并整理出一份可直接对照学习的资源导航与示例项目清单。读完本文你将能够判断自己的项目是否适合采用模块化单体并掌握落地它所需的核心概念与学习路径。一、什么是模块化单体定义与核心特征awesome-software-architecture 仓库在 README.md 中对本主题给出了精确定义Modular Monolith is an architectural approach that combines the advantages of monolithic and microservices architectures. It aims to build a monolithic application with a modular design that allows it to be divided into smaller, more manageable parts, each with its own clear responsibilities and interfaces. This approach allows teams to develop and deploy features independently, while still maintaining a single codebase and database. The modular design also facilitates the testing and maintenance of the application, as well as the scaling of individual modules.即模块化单体是单体形态 微服务思维的结合体。它具备以下核心特征单一代码库与单一部署单元整个系统仍然作为一个进程、一个应用部署运维模型与传统单体一致模块化设计应用内部被划分为若干职责清晰、接口明确的模块Module每个模块都可以被独立理解、测试与维护团队协作友好不同团队可以在同一代码库中围绕各自模块独立开发减少相互阻塞数据库统一但逻辑隔离共享一个数据库但数据访问与领域逻辑按模块隔离可演进性模块边界一旦清晰未来可以按模块逐个拆分出去演化为微服务。它和传统单体即 Big Ball of Mud 大泥球反模式的本质区别在于有没有显式的模块边界与依赖规则。代码 opinion 社区的经典论断Long live the Monolith! Monolithic Architecture ! Big Ball of Mud正是强调——单体架构本身不是问题失去边界、纠缠不清的单体才是问题。三种架构形态的直观对比维度传统单体大泥球模块化单体微服务部署单元单个单个多个独立部署代码组织无边界、相互纠缠显式模块、清晰接口独立服务、独立仓库团队自治低中模块级自治高服务级自治运维复杂度低低高独立扩展不支持有限可水平复制整体支持按服务扩展演进成本拆分困难可按模块渐进拆分已拆分二、为什么选择模块化单体架构驱动因素Kamil Grzybek 的《Modular Monolith: Architectural Drivers》该主题的经典文章已收录于本仓库精选清单系统梳理了选择模块化单体的架构驱动因素。综合本仓库 微服务文档 与 事件驱动架构文档 的论述常见驱动因素包括1. 团队规模与组织形态不匹配微服务微服务的主要收益之一是让团队独立交付但其代价是分布式系统固有的复杂度网络故障、分布式事务、服务发现、可观测性等。当团队规模较小如一到两个团队时直接上微服务往往得不偿失——这正是 Martin Fowler《MonolithFirst》的核心观点除非有明确需要否则先从单体开始而带好边界的单体即模块化单体是最佳的中间形态。2. 需要保留单一事务边界模块化单体共享同一个数据库与同一个事务管理器跨模块的业务操作可以保持 ACID 事务。而微服务一旦拆分数据库就必须面对分布式事务与最终一致性的复杂问题。若业务强一致性需求较多模块化单体是更务实的选择。3. 开发体验与启动成本相比微服务模块化单体只需启动一个进程本地调试、端到端测试、重构工具链都简单得多。仓库清单中 [Easy Modular Monolith 系列文章]MVP、Outbox、日志、全局异常处理、JWT 认证等六篇正是围绕如何低成本地把一个模块化单体搭建起来展开的实战教程。4. 保留向微服务演进的选项模块化单体最重要的价值之一是演化优先当某个模块的负载、团队或发布频率确实需要独立扩展时可以只拆这一个模块而不是像大泥球单体那样推倒重来。仓库清单中 Chris Richardson 的《Decompose Your Monolith》系列与 Milan Jovanović 的《Breaking It Down: How to Migrate Your Modular Monolith to Microservices》都演示了这种渐进式拆分路径。何时应该直接选择微服务结合仓库 微服务文档 的论述当出现以下信号时才应考虑真正拆分微服务存在多个需要独立扩展、独立发布的高竞争模块团队规模足够大每个服务都能由独立团队长期维护已经具备分布式运维能力容器编排、服务网格、可观测性等业务允许跨服务采用最终一致性模型。三、模块化单体的核心设计原则3.1 模块边界用有界上下文划分模块模块划分是模块化单体的第一要务。DDD领域驱动设计中的有界上下文Bounded Context是划分模块边界的黄金标准每个模块对应一个独立的有界上下文拥有自己的通用语言Ubiquitous Language与领域模型。仓库中的 有界上下文文档 与 战略设计模式文档 给出了判断边界的系统方法通过事件风暴Event Storming等建模手段识别业务能力进而确定每个上下文的范围与彼此之间的关系共享内核、防腐层、开放主机服务等。Kamil Grzybek 的参考实现 modular-monolith-with-ddd本仓库清单首推的完整示例正是按有界上下文划分模块的教科书级示范每个模块独立包含自己的领域层、应用层与基础设施层模块之间禁止跨边界直接引用领域对象。3.2 模块内高内聚、模块间低耦合内聚一个模块内的代码应围绕同一业务能力组织即所谓按功能/切片组织而非按技术分层组织。这与仓库中 垂直切片架构文档 的思想一致——一个模块内部可以由若干垂直切片组成每个切片覆盖从 API 到持久化的完整请求路径耦合模块间只能通过公开接口模块对外暴露的 API 或消息契约交互禁止模块 A 直接读取模块 B 的数据库表也禁止 A 直接 new 出 B 的内部类。仓库清单中 Lukasz Reszke 的《SHARING DATA BETWEEN MODULES IN MODULAR MONOLITH》专门讨论了模块间数据共享的边界问题共享什么、不共享什么、如何共享。3.3 模块间通信同步调用与异步消息模块间通信是模块化单体中最容易被做坏的部分主要有两种模式同步通信模块 A 直接调用模块 B 提供的公开服务接口如方法调用或内部 HTTP/契约调用。优点是简单直观、结果立等可取缺点是形成运行时耦合且调用链变长后难以独立扩展。仓库清单中 [Easy Modular Monolith 系列] 的 Part 6 专门讲解模块间同步通信的实现方式。异步通信事件驱动模块通过发布集成事件Integration Events解耦。仓库中的 集成事件文档 与 事件驱动架构文档 详细介绍了这一模式事件发布方只负责发布发生了什么事订阅方自行决定如何响应双方互不知晓对方存在。同时领域事件文档 区分了领域事件进程内、领域层内部与集成事件跨模块/跨服务边界——在模块化单体内模块间通信应使用集成事件而领域事件主要用于模块内部的领域逻辑编排。可靠消息投递Outbox 模式。事件发布与业务数据提交必须保持原子性否则会出现数据已保存但事件没发或反之的一致性漏洞。仓库中的 Outbox 模式文档又称事务性发件箱/Transactional Outbox给出了标准解法在同一数据库事务中写入业务数据与待发送事件到 outbox 表再由后台进程或 CDC 变更数据捕获将事件投递到消息中间件实现至少一次投递at-least-once。[Easy Modular Monolith 系列] 的 Part 2 正是以 Outbox 模式为主题。3.4 架构强制Architecture Enforcement模块边界若只停留在约定层面最终必然腐化。Kamil Grzybek 的《Modular Monolith: Architecture Enforcement》一文专门讨论如何用工具与测试强制架构规则常见手段包括依赖方向控制通过架构测试如 .NET 的 NetArchTest、Java 的 ArchUnit断言模块依赖图禁止反向依赖与跨模块引用模块可见性限制利用编译层面的访问修饰符如 C# 的internal与InternalsVisibleTo将模块内部类型对外不可见只暴露明确的公开门面Facade独立解决方案/独立程序集Jon P Smith 的《Evolving modular monoliths: 2. Breaking up your app into multiple solutions》展示了把每个模块拆成独立程序集甚至独立解决方案的做法从物理结构上保证模块边界不可绕过CI 校验在持续集成流水线中加入架构规则检查一旦违反即构建失败。3.5 与 DDD、CQRS、Clean Architecture 的结合模块化单体与多种架构风格天然互补仓库清单与配套文档均可佐证DDD用有界上下文划模块用聚合、值对象、领域事件等战术模式充实模块内部。参考 DDD 文档、战术设计模式文档 以及示例 AwesomeBank.NET 5.0 DDD CQRS 模块化单体CQRS模块内部可分别优化读写模型参考 CQRS 文档Clean ArchitectureJon P Smith 的《My experience of using the Clean Code architecture with a Modular Monolith》与 Clean Architecture 文档 探讨了在模块内部应用依赖倒置与分层的问题垂直切片模块内部按业务功能垂直组织参考 垂直切片架构文档 及示例 DDD-VShop每个模块都是带自定义架构的独立垂直切片。四、好的单体与坏的单体警惕 Big Ball of Mud模块化单体最大的风险是退化为大泥球。仓库 Big Ball of Mud 文档 指出大泥球是没有任何可识别的架构、边界模糊、代码相互纠缠的反模式。判断一个单体是好单体还是坏单体可以看好单体可称为模块化单体坏单体大泥球有显式模块边界与公开接口无边界任意类可互相引用依赖方向受控、单向依赖图混乱、循环依赖数据访问按模块隔离各层代码直连共享数据库表有架构测试强制规则依赖代码评审口头约定可按模块独立测试牵一发而动全身Tomas Tulka 的《Good and Bad Monolith》与 CodeOpinion 的《Long live the Monolith! Monolithic Architecture ! Big Ball of Mud》均以好/坏单体二分法为主题是理解这一区别的最佳入门材料。仓库中 内聚与耦合文档、耦合文档 也可作为模块设计的理论依据。五、演进路线从单体到模块化单体再到微服务5.1 MonolithFirst先单体后拆分Martin Fowler 的《MonolithFirst》主张在缺乏明确拆分理由时应先构建单体即使未来需要微服务从一个模块化良好的单体出发也比从零设计分布式系统容易得多。仓库清单中《Build the modular monolith first》进一步强化了这一观点把模块化单体作为默认起点。5.2 渐进式分解的十条原则Chris Richardson 在《Decompose your monolith: Ten principles for refactoring a monolith to microservices》中给出了从单体分解为微服务的原则框架与《Decompose Your Monolith: Strategies for Migrating to Microservices》互为补充。核心要点包括围绕业务能力与有界上下文切分、先以模块/代码边界开始、用 Strangler Fig绞杀者模式渐进替换、优先处理数据所有权等。仓库中的 Strangler Fig 模式文档 与 模块间通信/服务边界 可作为配套参考。5.3 从模块化单体到微服务的具体步骤Milan Jovanović 的《Breaking It Down: How to Migrate Your Modular Monolith to Microservices》给出了从模块化单体拆分的实战路径概括为模块边界先行确保每个待拆模块已经拥有完整、独立的数据与逻辑边界这正是一开始就采用模块化单体的意义所在通信契约化将模块间同步调用逐步替换为事件/消息契约使拆分后仍能通信数据拆分把共享数据库按模块拆分为独立库通过事件溯源、CDC等手段迁移数据独立部署逐个将模块抽取为独立服务利用 API 网关、服务发现等基础设施补齐分布式能力基础设施补齐分布式事务采用 Saga参考分布式事务文档与最终一致性文档。需要强调的是拆分应是按需、增量的只有当某个模块确实需要独立扩展/独立发布时才拆切忌为了微服务而微服务。六、仓库精选资源导航以下分类导航覆盖 docs/modular-monolith.md 中的全部精选资源文章、视频与示例项目。该文档是持续维护的完整清单建议对照原文档获取最新链接与标注。6.1 基础资源与入门必读Simon Brown《Modular Monoliths》GOTO 大会演讲幻灯片模块化单体概念的奠基性材料另配有 2016/2018 等多个演讲视频Kamil Grzybek《Modular Monolith: A Primer》模块化单体入门经典系统介绍定义、动机与结构Kamil Grzybek《Modular Monolith: Architectural Drivers》深入分析选择该架构的驱动因素与权衡Kamil Grzybek《Modular Monolith: Architecture Enforcement》讲解如何用工具与测试强制架构规则Martin Fowler《MonolithFirst》先构建单体的方法论论据《Modular Monolith - A Gentle Introduction》与《Implementation Deep Dive》DanDoesCode入门到实现的配套阅读《Making Modular Monoliths Work》Sookocheff讨论让模块化单体真正生效的实践条件《A Practical Guide to Modular Monoliths with .NET》chrlschn.dev⭐仓库清单标注的推荐实践指南《Modular programming: Beyond the spaghetti mess》Tiny.cloud从模块化编程原理出发理解模块化单体。6.2 架构权衡与定位CodeOpinion 系列《Loosely Coupled Monolith Overview》《Long live the Monolith! Monolithic Architecture ! Big Ball of Mud》《Scaling a Monolith Horizontally》——分别讨论松耦合单体概览、单体≠大泥球、单体水平扩展《Why using Microservices or Monolith can be just a detail?》ThreeDotsLabs指出单体与微服务的选择本质上应服从于业务与团队约束《Thoughts on Modular Monoliths》《Actually Talking about Modular Monoliths》《Modular Monoliths and the Critter Stack》Jeremy D. Miller对模块化单体的批判性思考与工具栈讨论《Majestic Modular Monoliths》Lukas Hajdu探讨雄伟的模块化单体形态另有 Axel Fontaine 的同名演讲视频《Improving Monoliths Availability》《Scaling a Monolith Horizontally》讨论单体的可用性与扩展性提升手段《Good and Bad Monolith》Tomas Tulka好单体与坏单体的判别《How to quickly scale a legacy monolith?》event-driven.io以事件驱动方式快速扩展遗留单体。6.3 模块设计、通信与数据共享《SHARING DATA BETWEEN MODULES IN MODULAR MONOLITH》Lukasz Reszke模块间数据共享的边界问题《Event Modeling Modular Monolith | From colored cards to code through TDD》用事件建模 TDD 从卡片到代码落地模块化单体《My experience of using modular monolith and DDD architectures》与《My experience of using the Clean Code architecture with a Modular Monolith》Jon P SmithDDD 与 Clean Architecture 在模块化单体中的真实使用经验《Evolving modular monoliths: 1. An architecture for .NET》与《Evolving modular monoliths: 2. Breaking up your app into multiple solutions》Jon P Smith.NET 下模块化单体的架构演进与多解决方案拆分。6.4 端到端实战系列Easy Modular MonolithPart 1 — MVP从最小可行产品起步搭建模块化单体Part 2 — OutBox Pattern用事务性发件箱保证事件可靠投递Part 3 — LoggingSerilog 和 Seq日志与可观测性接入Part 4 — Global Exception Handling全局异常处理Part 5 — JWT Authentication/Authorization认证与授权Part 6 — Synchronous communication between modules模块间同步通信。该系列完整覆盖了一个模块化单体从零到可用的全部关键环节是最适合动手跟练的实战教程。6.5 演进与迁移InfoQ《Migrating Monoliths to Microservices with Decomposition and Incremental Changes》分解与增量变更的迁移方法论Chris Richardson《Decompose your monolith: Ten principles…》与《Decompose Your Monolith: Strategies…》单体分解的十条原则与迁移策略Milan Jovanović《Breaking It Down: How to Migrate Your Modular Monolith to Microservices》从模块化单体到微服务的迁移步骤《Monolithic to Microservices Architecture with Patterns Best Practices》模式与最佳实践视角的迁移综述《Build the modular monolith first》把模块化单体作为默认起点的论证。6.6 视频资源精选Simon Brown 系列GOTO 2018《Modular Monoliths》、2016 版及专题演讲——概念奠基Sam Newman《GOTO 2019 Monolith Decomposition Patterns》单体分解模式《GOTO 2016 From Monolith to Microservices at Zalando》大型电商平台真实迁移案例CodeOpinion 系列《Creating a Loosely Coupled Monolith》《Solution Project Structure of a Loosely Coupled Monolith》《Asynchronous Messaging in a Loosely Coupled Monolith》《Avoiding a Big Ball of Mud! Coupling in a Monolith》——松耦合单体的创建、结构、异步通信与防腐化《START with a Monolith, NOT Microservices》为什么从单体开始《Message Driven Architecture to DECOUPLE a Monolith》用消息驱动架构解耦单体《Deconstructing the Monolith》Shopify Unite 2019大型单体拆解的工程实践《Building that glorious monolith. And carving it too.》NDC Oslo 2022⭐与《A Practical Guide to Modular Monoliths with .NET - Build Web Scale Monolithic Architectures》⭐仓库清单重点标注的进阶演讲《How to design and code a scaleable solution (from monolith to microservices)》从单体到微服务的可扩展设计编码《Scaling Monolithic Applications》《Splitting up a Monolith to (micro)Services》扩展与拆分专题。6.7 示例项目按技术栈分类DDD 驱动的 .NET 模块化单体学习首选kgrzybek/modular-monolith-with-ddd完整的 DDD 模块化单体参考实现模块划分与架构强制的最佳范本配套 React 前端仓库 modular-monolith-with-ddd-fe-reactmarcinstelmach/AwesomeBank.NET 5.0 DDD CQRS 的银行系统DijanaPenic/DDD-VShop.NET 6 模块化单体每个模块是独立的垂直切片kamilbaczek/Estimation-Tool 与 kamilbaczek/Modular-monolith-by-example ⭐.NET 模块化单体示例IT 估算工具业务域evolutionary-architecture/evolutionary-architecture-by-example ⭐以故事化方式讲解模块化单体与微服务、DDD 的交互dcomartin/LooselyCoupledMonolith松耦合单体实践Nairda015/IGroceryStore松耦合单体应用DarekModzelewski/Contoso-University-DDD经典 Contoso 大学示例的 DDD 化改造chrisklug/asp-net-modular-monolithASP.NET 模块化单体示例Ridikk12/ModularMonolith模块化单体通用示例PeterKneale/modular_monolith_saasSaaS 场景的模块化单体。.NET 8 现代模板与脚手架CharlieDigital/dn8-modular-monolith ⭐.NET 8 模块化单体momo实战示例baranacikgoz/modular-monolith-ddd-vsa-webapi.NET 8 模板整合模块化单体 DDD 垂直切片 Clean Architectureyoussefbennour/AspNetCore.Starter受 evolutionary-architecture 启发的模块化单体 Starterphongnguyend/Practical.CleanArchitecture同一业务在微服务、模块化单体、单体三种形态下的 Clean Architecture 对照实现。电商/业务系统真实规模参考simplcommerce/SimplCommerce.NET Core 模块化电商系统nopSolutions/nopCommerce基于 ASP.NET Core 的开源电商grandnode/grandnode 与 grandnode/grandnode2ASP.NET Core MongoDB 的电商方案含 headless、多租户版本smartstore/SmartStoreNETASP.NET MVC 企业级电商trueai-org/module-shop模块化商城thangchung/coolstore-moduliths 与 thangchung/coffeeshop-modularcoolstore/coffeeshop 业务的模块化实现thangchung/blog-coreBlazor 领域驱动模式的模块化博客VirtoCommerce/vc-storefrontVirtoCommerce Storefrontddd-by-examples/library问题空间战略分析与战术模式的综合 DDD 示例。其他语言生态anton-liauchuk/educational-platformJava 模块化单体 DDDttulka/ddd-example-ecommerceJava Spring 的 DDD 电商ttulka/ddd-example-ecommerce-kotlinKotlin Spring 版本mgce/modular-monolith-nodejsNode.js 模块化单体实现stemmlerjs/ddd-forumTypeScript 的 DDD 论坛应用ThreeDotsLabs/monolith-microservice-shop配合《Microservices or Monolith is just a detail?》文章的配套源码drminnaar/chinook架构、设计、.NET Core/TypeScript/React/Docker 的综合试验场。七、学习路径建议结合上述资源推荐按以下顺序建立模块化单体的完整知识体系概念入门先读 Simon Brown 的演讲材料与 Kamil Grzybek 的《A Primer》建立单体形态 模块思维的整体认知边界设计通过 有界上下文文档 与 战略设计模式文档 掌握模块划分方法对照 modular-monolith-with-ddd 查看真实模块结构通信机制阅读 集成事件文档、Outbox 模式文档 与 事件驱动架构文档理解同步/异步通信与可靠投递动手实践按 [Easy Modular Monolith 系列] 六篇文章从零搭建一个带认证、日志、异常处理与 Outbox 的完整模块化单体防腐化与演进学习架构强制手段Architecture Enforcement再通过 Chris Richardson 与 Milan Jovanović 的迁移文章掌握按需拆分为微服务的增量路径配套参考 Strangler Fig 模式文档 与 分布式事务文档持续跟进回到仓库清单 docs/modular-monolith.md 获取持续更新的文章、视频与示例项目并结合仓库内 微服务文档、DDD 文档、垂直切片文档 等主题深化理解形成单体起步、模块组织、按需拆分的完整架构决策链。结语模块化单体并非逃避微服务的妥协方案而是一种尊重业务边界、控制分布式复杂度、保留演进自由的架构选择。它用工程纪律模块边界、依赖规则、架构强制弥补了单体在组织层面的天然短板又用单一部署与单一事务换来了微服务所不具备的简单性。对于大多数团队而言先构建一个模块化良好的单体再按需演进比一步到位地引入微服务更务实、更可持续。本仓库的精选资源与示例项目为这条路径提供了从理论到实践的全套弹药值得系统研读。【免费下载链接】awesome-software-architecture A curated list of awesome articles, videos, and other resources to learn and practice software architecture, patterns, and principles.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-software-architecture创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考