本文目录
先降低业务耦合,再决定是否增加分布式复杂度
模块化单体在同一部署中约束业务边界和调用关系,适合先解决代码纠缠、共享规则和测试困难。只有独立扩展、独立交付或团队自治的收益明确,且具备服务运维能力时,抽取微服务才更有依据。把目录拆开或者把进程拆开都不足以完成架构升级,应证明模块对外接口、依赖方向和数据责任能够持续受约束。
模块化与独立服务的选择
| 方式 | 值得采用的信号 | 主要负担 |
|---|---|---|
| 模块化单体 | 主要困难是内部耦合,统一部署仍能满足业务 | 需要架构规则和持续检查,不能靠口头约定保持边界 |
| 抽取边缘服务 | 某能力有独立容量或发版需求,边界与责任清楚 | 需要接口版本、网络故障处理和独立值守 |
| 全面微服务 | 多个稳定业务域确需独立运营且组织能够支持 | 跨服务协作、链路诊断和一致性成本显著增加 |
从业务动作和规则归属划分模块
订单、客户和审批可以作为讨论起点,但名称不等于边界。要看哪些规则一起变化、哪些状态由谁拥有,以及哪些操作需要一致完成。
让业务人员解释一次完整任务,再把计算、状态和资源归属画出来。按控制器、服务层和数据层切目录有助于组织代码,却不能替代业务边界。对模块间共同使用的概念明确含义,避免“客户”在销售和结算中被迫使用同一套不断扩展的对象。
- 为每个模块说明职责、对外能力和禁止承担的事项。
- 记录关键术语与状态含义,确认变化由谁负责。
- 将边界不稳定的能力先保留为较粗模块。
接口公开,内部实现不可随意访问
模块对外提供少量明确接口,其他模块通过接口请求能力。跨模块调用内部类、直接引用内部查询和循环依赖,都应成为可发现的问题。
先生成现有依赖关系,再列出允许的方向。必要的共享内容应保持小而稳定,不能把所有业务代码都移入“公共模块”。Java 项目可借助 Spring Modulith 等工具检查模块循环和内部访问,其他技术栈也可用相应静态规则;工具只是约束方式,规则本身仍要由团队设计。
暂存违规可以分期处理,但应限制新增数量并清楚登记。自动检查发现问题后,需要有能够落实的修正路径,而不是长期忽略全部警告。公开接口改动还要评审受影响调用方,防止内部结构清理破坏合法协作。
- 为公开接口写清输入、输出、错误和执行责任。
- 禁止新增未经批准的内部访问与依赖循环。
- 对暂时无法清理的违规登记位置、原因与期限。
统一数据库也要限制跨模块写入
模块化单体不要求立刻分数据库,但需要明确每类数据的写入主责。否则代码边界虽然清楚,业务规则仍会被绕过。
某模块拥有订单状态时,其他模块应请求其业务接口,而不是直接改状态字段。报表和查询需要跨域信息时,可明确读取方案和时效要求;不为了追求形式上的隔离,把所有查询都改成深长调用链。先约束写入,再评估读取与长期数据边界,避免把本期模块化变成完整数据库迁移。
- 建立表或业务对象的主责清单,列出当前越界写入。
- 将关键状态修改收敛到所属模块的业务命令。
- 报表与批处理同样遵守规则,不作为默认例外。
选择一条业务链完成纵向模块化
先把一个流程的接口、规则和数据责任整合到所属模块,再逐步处理其他功能。只统一移动所有文件,很难验证是否改善了变化成本。
实施先确认边界和保护样例,再调整调用关系,随后增加自动检查。第一条业务链完成后,让新增需求按新边界实现,并观察是否仍需修改无关模块。发现多个模块反复一起改变时,应重新检视边界,而不是不断添加绕过规则的例外。用实际变更评审验证结构是否便于工作。
- 第一步:选定业务链并记录现有依赖与关键行为。
- 第二步:建立公开接口,收敛规则与写入入口。
- 第三步:持续检查边界,核对后续需求的影响范围。
抽取服务需要回答运营收益和故障责任
独立服务可能满足不同资源需求、发版节奏或团队自治,但也增加网络调用、接口兼容和跨进程诊断。收益与新增责任应一起说明。
候选服务应有稳定接口、清楚的数据主责和独立运行条件。团队需要说明服务不可用时主流程怎样表现、谁处理告警、如何联调和发布。若模块仍需要每次同步改另一半系统,独立部署带来的收益有限。优先从边界已验证、收益可解释的模块抽取,避免一次把所有模块变成服务。
试抽取后记录额外环境、接口适配和运行支持工作,并与预期收益比较。若维护负担超过收益,保留进程内模块也是可接受结论;已经拆成服务的形式,不应迫使团队继续扩大一个尚未被证实的方案。
- 记录独立容量、独立发布或团队自治的具体需求。
- 评估网络失败、超时、重复处理与接口版本管理。
- 指定独立服务的值守、运维、测试和交付责任。
模块化验收看边界能否保持,性能另行验证
验收证据包括依赖检查、越界写入治理、模块测试和新增需求的实际影响。服务数量、目录数量和框架名称不能证明升级完成。
本文适合业务仍持续变化、统一部署尚能工作的旧系统。如果已有明确隔离监管要求或技术上必须分开运行,独立部署条件应更早纳入方案。模块化不会自动缩短响应时间,微服务也不会自动提高并发能力;涉及容量目标时,应按实际业务负载验证,并与本期结构成果分别记录。
- 在持续集成中检查依赖方向与允许访问范围。
- 保留规则测试和公开接口的契约说明。
- 列明剩余架构违规与选择暂不抽取的原因。
需求讨论中的问题
模块化单体会不会阻碍以后拆微服务?
清楚的接口、数据主责和依赖方向通常有助于后续抽取,但不是自动拆分的保证。真正抽取时仍要设计网络故障、接口兼容和独立运行。
多个模块使用同一数据库算不算模块化?
可以。关键是数据责任和访问约束可执行,特别是关键写入不能随意越界。是否分数据库取决于隔离需求和投入,不是目录划分的附带要求。
微服务是不是一定更适合高并发?
不能这样推断。容量受业务负载、数据访问、资源和依赖限制共同影响。独立扩展可能有用,但需要明确瓶颈并经过实测。
单体模块化的 8 项验收
可逐项勾选,辅助本次阅读;刷新页面后不保留。
参考资料
技术概念可进一步阅读以下资料;文中的业务场景与实施清单用于方案讨论。
- Spring Modulith · Verifying Application Module Structure
核对模块无循环、内部访问限制和允许依赖的结构验证能力。
- Microsoft Azure Architecture Center · Domain analysis
核对业务域分析与边界识别方法;本文模块化决策不要求采用 Azure。
- Martin Fowler · Monolith First
核对服务边界稳定性与微服务运营成本的原始讨论,作为决策依据而非普遍结论。
旧单体难以维护,正在考虑微服务?
提供模块关系、发版困难、容量需求和团队运维能力,月弦科技可以帮助评估模块化与服务抽取的先后顺序。