单体、微服务、Serverless:架构要匹配问题

单体、微服务、Serverless:架构要匹配问题

《工程化决策树》第 2 篇

架构选型不是给项目评成熟度,而是在业务不确定性与分布式成本之间作取舍。


一、三个人维护了一套为未来准备的系统

一个 3 人创业团队在做 SaaS 产品,前端是 React 和 Next.js,后端拆成用户、订单、支付、通知 4 个服务;基础设施用了 Kubernetes、Istio、Kafka、Prometheus、Grafana 和 Jaeger,每个服务还有独立的 PostgreSQL。

这套组合并非技术上不可行,问题是它解决的还不是团队当时最紧迫的问题。产品上线 4 个月,累计约 200 个用户,日活不到 20。需求仍在快速变化,3 个人中却有 1 个人长期维护基础设施。改一次订单流程要跨服务联调,通知服务的同步故障还曾阻断下单。

根据他们当时的云账单,每月成本约 8000 元。我建议先合回一个部署单元和一个数据库,保留清晰模块边界。重构后账单降到约 2000 元,原来维护基础设施的人也重新参与业务开发。之后两个月,调整后的架构承载了产品当期增长;用户增长受产品和市场等多种因素影响,不能归因于这次重构。

这些人数、用户量和成本只属于这个项目,不是"低于某个日活必须用单体"的行业阈值。这个案例暴露的是错位:团队主要风险还是需求能否被验证,架构却在提前支付分布式协作和运行成本。

二、三个选项,三组约束

单体:减少运行边界

单体把代码放在一个部署单元里,通常也从一个主要数据库开始。它的优势是本地调用、事务、调试和部署路径短,适合业务边界尚未稳定,或者团队能在一个交付节奏内协作的场景。

单体不等于把所有逻辑写进一个目录。没有模块边界、依赖任意穿透的单体会逐渐难以修改;按领域划分模块、限制依赖方向的模块化单体,仍然可以保持一个部署单元。

它的压力通常来自三处:整个应用一起发布,局部负载难以独立扩缩,多个团队在同一代码和数据边界上互相阻塞。当这些压力尚未出现,提前拆服务不会自动带来收益。

微服务:用分布式成本换独立性

微服务把业务边界变成独立部署和运行边界,适合需要独立发布、独立扩缩容、故障隔离或团队自治的模块。

收益成立有个前提:边界确实相对稳定,而且独立性带来的价值高于以下成本。

新增成本 团队要回答的问题
网络通信 超时、重试、幂等和降级如何处理
数据边界 跨服务查询与一致性由谁负责
发布数量 多服务如何部署、兼容和回滚
故障定位 日志、指标和链路如何关联
所有权 谁维护服务,谁响应故障

服务拆开只完成了物理分离。没有所有权、监控和回滚,团队得到的往往是更多故障面,而不是自治。

Serverless:把执行模型交给平台

Serverless 不是只能附着在单体旁边的"小插件"。如果业务天然事件驱动、请求可以短时无状态执行,团队接受托管平台的部署和运行方式,它完全可以成为后端主体。

判断它能否做主体,要逐项检查:

  • 执行模型: 任务能否拆成平台支持的请求、事件或工作流?运行时限和状态外置是否可接受?
  • 可观测性: 分散的函数、队列和托管服务能否形成统一的日志、指标与追踪?
  • 延迟: 冷启动、跨服务调用和地域距离是否满足用户路径要求?不同平台和配置下表现差异很大。
  • 成本曲线: 调用、执行时长、内存、流量和托管服务如何共同计费?应以实际负载测算,不能套一个通用"反转点"。
  • 供应商耦合: 身份、消息、工作流和数据库越依赖专有能力,迁移成本越高;耦合可以接受,但要有意识地选择。
  • 团队能力: 团队是否理解异步、幂等、重试、权限和云端调试,而不只是会写一个函数?

持续稳定负载、长连接、重计算和强本地调试需求,可能让容器或常驻进程更合适;流量波动、事件驱动和托管能力丰富的业务,则可能从 Serverless 获益。最终仍要看工作负载,而不是"主体"或"插件"的标签。

三、先看不确定性,再看协作压力

团队人数、日活和代码量都只是代理信号。对架构更直接的两个问题是:业务边界有多不确定,以及独立交付的压力有多大。

业务不确定性 协作 / 扩缩压力 更常见的起点 需要保留的警惕
单体或模块化单体 快速反馈,但不要让模块任意耦合
模块化单体,必要处用托管能力 团队边界可能仍在变,避免全盘拆分
局部升高 按瓶颈拆分 一次只验证一个拆分收益
微服务,或 Serverless / 容器组合 平台能力、数据治理和所有权必须跟上

"压力"也不只有流量。两个模块需要不同发布节奏、故障必须隔离、合规要求数据分区,或多个团队在同一仓库频繁互相等待,都可能构成拆分理由。

反过来,流量上升不等于立即拆服务。缓存、索引、查询优化、异步处理、只读副本和局部独立部署,有时能用更低成本解决瓶颈。先定位问题,再改变边界。

四、模块化单体为什么常是推荐起点

我通常建议需求仍在验证的团队从模块化单体开始:一个部署单元,代码按业务域分开,模块之间通过明确接口协作,数据库访问也有所有权边界。

text 复制代码
应用
├── accounts    账户与权限
├── orders      订单规则与状态
├── payments    支付编排
└── notifications 通知策略

约束:
- 模块不直接调用另一个模块的内部实现
- 跨模块行为通过公开接口或领域事件表达
- 数据表有明确所有者,跨模块写入需要经过所有者

这样做的价值不只是"以后好拆"。即使永远不拆,边界也能降低修改时的认知负担。真出现局部瓶颈时,团队还有相对清楚的候选边界。

但"先单体、后拆分"只是推荐起点,不是宇宙定律。下面这些条件可能让项目从一开始就选择分布式或 Serverless:

  • 已知的合规或安全边界要求物理隔离。
  • 工作负载天然分布在不同地域、运行环境或硬件上。
  • 多个成熟团队已经有稳定域边界和平台能力,需要独立发布。
  • 业务高度事件驱动,托管服务能显著减少非核心运维。
  • 现有组织或遗留系统决定了集成边界,合并反而成本更高。

关键不是先后顺序,而是能否说清楚:为什么需要这个边界,以及团队是否承担得起它。

五、从瓶颈出发的决策树

text 复制代码
当前最贵的问题是什么?
│
├── 需求变化快、领域边界不稳定
│   └── 优先单体或模块化单体,缩短反馈路径
│
├── 事件突发、运维能力有限
│   └── 评估 Serverless 是否匹配执行模型与成本曲线
│
└── 已出现明确瓶颈
    ├── 能否在现有边界内解决?
    │   ├── 能 → 先做索引、缓存、异步或局部扩容
    │   └── 不能 → 继续判断
    ├── 候选模块能否独立拥有数据与发布节奏?
    │   ├── 不能 → 先整理模块与数据边界
    │   └── 能 → 继续判断
    └── 团队能否部署、观测、回滚并处理一致性?
        ├── 不能 → 先补齐工程能力
        └── 能 → 拆出该瓶颈,验证收益后再决定下一步

这棵树刻意不从"团队有多少人"开始。人数增加会放大协作压力,却不能证明微服务一定比单体好;少量工程师也可能因为合规隔离或特殊计算负载,合理维护少数独立服务。

每次拆分都应该带着可验证的目标,例如缩短某模块发布等待、隔离某类故障、降低某个负载的扩容成本。目标达成后再继续,避免把"拆完"本身当作成功。

六、回到那个三人团队

那个 SaaS 项目合回单体后,并没有把 4 个模块重新揉成一团。我们保留用户、订单、支付和通知的代码边界,只把同步网络调用改回进程内接口,把数据库收回同一个实例管理。

观察项 调整前 调整后
主要精力 业务开发与基础设施维护并行 更多时间回到业务验证
订单变更 跨服务修改与联调 在模块边界内修改和测试
故障面 网络、消息和多服务发布共同参与 单一部署路径,依赖更少
云资源 当时账单约 8000 元 / 月 当时账单约 2000 元 / 月

后来流量增长时,团队先处理了热数据缓存、读写压力和重查询模块,没有立即恢复全套微服务。这个选择在当时够用,但不能推出"某个日活以下都不需要微服务"。如果它是金融交易、实时协作或重计算产品,同样的用户量可能产生完全不同的压力。

我从这次经历里保留的判断是:先让监控告诉你瓶颈在哪里,再让边界跟着瓶颈变化。不要让想象中的未来流量,提前决定今天所有的部署单元。

七、选型前的检查清单

维度 要回答的问题 答不上来时先做什么
业务阶段 主要风险是需求不成立,还是现有系统无法承载? 先确认风险,不急着比较技术名词
领域边界 模块是否有稳定职责和数据所有权? 先在代码内建立模块边界
瓶颈证据 性能、发布、故障或合规压力具体在哪里? 补指标、追踪和实际测量
独立收益 拆分后哪项指标或协作问题会改善? 写出可验证目标
交付能力 多个单元能否自动部署、兼容升级和回滚? 先补 CI/CD 与发布策略
运行能力 能否关联日志、指标、链路和告警? 先建立可观测性
数据一致性 跨边界操作如何保证幂等、补偿与对账? 先设计失败路径
成本模型 正常、峰值和增长负载分别花多少钱? 用实际工作负载测算
团队所有权 谁维护平台,谁响应每个服务的故障? 明确责任与值守能力
退出条件 何时需要换方案,迁移代价是什么? 记录决策和复评信号

如果这些问题没有答案,先补证据通常比先画服务边界更有价值。

下一篇讨论代码组织:分层不是把文件放进 Controller、Service、Repository 三个目录,而是让变化被限制在可以理解的范围内。

上一篇:需求先把歧义问清,别把返工拖到交付后

下一篇:Controller 为什么会变胖:先拆职责,再谈分层


《工程化决策树》第 2 篇 · lytao123

相关推荐
javaDocker1 小时前
金融级 AIOps 架构跃迁(从“1-5-10“快恢目标到 AI Agent 告警收敛的完整技术实践)
人工智能·金融·架构
数字孪生视频孪生3 小时前
三维实时重构异构底座 核工危化无感定位跨境轨迹一屏统揽
大数据·运维·人工智能·重构·架构
数脉3 小时前
让每一条数据都有来龙去脉:我们的列级数据血缘平台功能全景
架构
Forerror20264 小时前
深入理解大模型网关是什么:MAI Gateway架构与核心价值解读
架构·gateway
ZStack开发者社区4 小时前
虚拟化观察 第 001 期:ZSvirt 核心 IaaS 引擎开源,VMware Explore 2026 开幕,Proxmox VE 8 正式 EOL
架构·开源·云计算·vmware·云基础设施·proxmox
河北清兮网络科技4 小时前
直播APP开发怎么选?流媒体高端定制架构解析,避开模板与外包技术坑
小程序·架构·app·短剧·短剧app·广告联盟
凤山老林5 小时前
高可用分布式任务调度架构:Spring Boot 集成 PowerJob 实战指南
spring boot·分布式·架构
拒绝内耗。5 小时前
程序员学架构(一):一张图看懂 Java 后端架构:一个请求怎样从手机到数据库?
java·智能手机·架构
~木雨5 小时前
Java 并发编程架构全景:并发层的五域设计 —— 线程模型、线程池隔离、并发安全到问题治理(全体系汇总)
java·安全·架构·线程池·并发编程·高并发架构