2024 之后新建后端服务,默认该选单体、模块化单体,还是直接拆微服务?
帖子正文与楼层回复。
背景
最近带团队评审一个全新业务线的技术选型,需求大概是:3 个后端 + 2 个前端,预计 18 个月内迭代 8~10 个功能域,QPS 峰值预估 2k 上下(B 端 SaaS)。团队里 3 个人立场几乎一致——"先拆服务,按业务域拆 4 个微服务,上 K8s + 网关 + mTLS"。我当场把方案打回去了,但没给出替代方案,因为我自己也没想清楚"替代方案到底长什么样"。
回来翻了下社区,看到有人做"垂直微服务"、有人坚持"模块化单体(modular monolith)"、还有人提"先单体跑半年再拆"——三派都有道理,但我发现大家讨论时几乎都不提团队规模和运维能力,只谈技术。我觉得这是最大的盲区。
我看到的三种常见做法
-
模块化单体(Modular Monolith):一个进程、一套部署,但代码按业务域强隔离(包 / 模块 / 编译期边界),数据库可以分 schema。代表:Spring Modulith、NestJS 的 monorepo 强约束、Go 的单 binary + 内部 service 分层。
- 优点:部署 1 份、链路追踪简单、跨模块调用是本地函数调用(P99 不会因为网络抖动放大)、新人上手 1 天就能跑通全链路。
- 代价:模块边界靠纪律维持,没有运行时强制;某个模块内存泄漏会拖垮整个进程;团队扩张到 10+ 人后代码评审会变成瓶颈。
-
业务域微服务:按领域边界拆 3~6 个服务,每个独立部署、独立数据库。
- 优点:故障隔离真实(一个服务挂了不影响其他)、团队可以并行迭代、扩缩容粒度细。
- 代价:分布式事务、服务发现、链路追踪、可观测性、灰度发布、接口契约管理——这一套基础设施的成本,小团队根本摊不平。我见过 3 人团队维护 6 个微服务的,最后 70% 时间在做"让服务之间说话",而不是做业务。
-
单体起步 + 预留拆分点:先按模块化单体的纪律写,关键边界(接口 / 事件 / 数据模型)按"未来可能拆"来设计,等真的撞上痛点(团队 >8 人、单模块 QPS 显著高、故障域需要隔离)再拆。
- 优点:前期成本最低,且拆分时因为边界清晰,迁移成本远低于"一开始就乱写"。
- 代价:需要团队真的按微服务的纪律写单体(模块间只通过接口 / 事件通信、不共享表),这对纪律要求其实比微服务还高。
我的倾向(带理由)
我倾向 3(单体起步 + 预留拆分点),但前提是:
- 团队规模 ≤ 6 人;
- 运维能力不足以支撑一套完整的 K8s + 网关 + 链路追踪栈(或者团队愿意接受"用云厂商托管服务来摊平这套成本");
- 业务域之间没有硬隔离要求(合规、多租户物理隔离、跨公司数据边界);
- 峰值 QPS 在单台 16C32G 机器上扛得住(2k QPS 的 B 端 SaaS,按我的经验,单体 + 好的连接池 + Redis 缓存,单机撑得住)。
如果上面任何一条不满足,我会直接上模块化单体 + 按域分 schema,而不是拆微服务——因为"模块化单体 + 多 schema"能拿到 80% 的隔离收益,但只需要 30% 的基础设施成本。
想听大家聊聊
- 你们团队现在用的是哪种?当时为什么这么选?事后看选对了吗?
- 你们有没有"一开始拆微服务,后来合并回单体"或反过来"一开始单体,后来被迫拆"的真实经历?是什么具体的痛点逼着你们改的?(我想听具体场景,不是"微服务解耦"这种空话)
- 模块化单体的"模块边界纪律",你们靠什么机制维持?代码评审?编译期约束?架构测试?
- 有没有人试过"垂直微服务"(一个垂直切片一个服务,不按域拆)?效果如何?
- 团队规模到多少人、QPS 到什么量级,你会主动从单体切到微服务?(我想收集一个经验分布,好给未来选型一个参考)
欢迎贴你踩过的坑、做过的取舍、以及当时的上下文。空谈"微服务解耦"的就不聊了,我们只聊具体场景下的具体取舍。