微服务到底解决了什么,又制造了什么?
我见过一种很典型的项目。
团队三四个人,业务还没真正上线,仓库里已经有:
gateway
auth-service
user-service
asset-service
workflow-service
notification-service
audit-service
再配 PostgreSQL、Redis、消息队列、对象存储、配置中心、链路追踪。开发机启动一次,十几个容器一起亮起来,看着确实很有“大系统”的感觉。
然后改一个登录字段。
前端要改,网关要改,认证服务要改,用户服务要改,Proto/OpenAPI 要重新生成,两个服务要一起发版,测试环境还得把依赖全拉起来。
这时候就该问一句了:
我们到底为什么要拆微服务?

图:AWS 官方对 Monolith 与 Microservices 的对比示意。
很多人第一次接触微服务,会把它理解成“把大项目拆小”。这个理解只说对了一小半。
如果只是代码太大,模块化单体、Package 边界、依赖倒置、DDD 分层都能解决相当一部分问题,而且便宜得多。
微服务真正值钱的地方,是独立性。
一个服务最好能由一支明确的团队负责,拥有自己的业务边界、代码、数据和发布节奏。它可以单独修改、单独测试、单独上线、单独扩容,出了问题也尽可能把影响限制在自己的边界里。
微软当前的 Azure Architecture Center 也把“独立部署”“独立扩缩容”“数据隔离”“小而聚焦的团队”列在微服务的核心收益里,同时明确提醒:微服务会引入服务发现、跨服务通信、数据一致性、事务管理和运维复杂度。
换句话说,微服务本质上是一笔交易。
你主动接受一部分分布式系统的麻烦,换取系统和团队在某些地方真正能够独立演进。
最实际的收益:发布边界终于可以缩小
假设一个大型单体里有订单、搜索、通知、用户、报表五块业务。
通知模块改了一行代码,理论上你可能仍然需要重新构建整个应用,然后把一个包含所有业务的新版本部署出去。
微服务拆得合理时,通知服务可以自己发布。
这件事对五个人团队未必值很多钱,但对几十支团队并行开发的大型组织,价值会非常明显。
真正的微服务通常伴随着一个现实组织问题:
我不希望 A 团队上线一个功能,还必须等 B、C、D 三个团队一起约窗口。
AWS 的官方指导甚至直接给出了“service per team”的模式:一个微服务由一支团队负责,团队能够独立开发、测试、部署和扩缩容,跨团队主要通过稳定 API 协商。
所以很多时候,微服务首先解决的是组织扩张以后产生的协作成本。
如果整个后端只有两个人,而且两个人每天坐在一起改同一个业务,先把系统拆成 18 个进程,收益往往没想象中大。
某一块特别吃资源时,终于不用全体陪跑
这也是微服务非常实在的价值。
比如你的系统里:
- 普通 REST API 只需要 2 核 4G;
- 文档解析非常吃 CPU;
- AI 推理需要 GPU;
- 文件转码需要大量临时内存;
- 消息消费可以异步慢慢处理。
如果它们全部塞在一个进程里,扩容经常只能把整个应用一起复制。
拆开以后,谁忙扩谁。
这也是 AWS 和微软都反复强调的 independent scaling。
这种场景下,服务边界有非常明确的资源意义,不是为了架构图更漂亮。
故障也可以有边界
设计得好的情况下,推荐系统挂了,用户仍然能登录;报表服务挂了,核心交易仍然能进行;邮件服务暂时不可用,订单可以先进入队列,晚点再通知。
这叫降级。
但注意前提:设计得好。
如果登录要同步调用用户服务,用户服务同步调用组织服务,组织服务同步调用权限服务,权限服务再同步查另一个服务,那么任何一个节点超时都可能把整条请求链拖死。
AWS Well-Architected Framework 甚至给这种东西起了一个很形象的名字:Microservice Death Star。
服务看起来很多,依赖线密密麻麻,任何一处变化都会沿着网络传播。
最后既没有单体简单,也没有微服务独立。
然后,账单来了
微服务最容易被忽略的一点,就是它把很多以前由进程内部保证的东西,交给了网络。
以前:
func A() -> func B()
现在:
service A
|
HTTP/gRPC
|
service B
图上只多了一条箭头。
工程上多出来的东西可不少:
- DNS 会不会解析失败;
- 连接会不会超时;
- 对方返回 500 怎么办;
- 请求已经执行成功,但响应丢了怎么办;
- 重试会不会造成重复写入;
- API 如何版本兼容;
- TLS 和服务身份怎么做;
- 链路怎么追踪;
- 对方发布新版本时自己会不会被带崩。
一次普通函数调用变成网络调用以后,“失败”从异常情况变成了日常设计的一部分。
这也是为什么微服务系统里 timeout、retry、circuit breaker、idempotency、trace ID 这些词出现得那么频繁。
一条数据库事务,也可能变成一篇论文
单体时代有个很好用的东西:数据库事务。
BEGIN;
UPDATE orders ...;
UPDATE inventory ...;
INSERT INTO payment_records ...;
COMMIT;
只要这些数据在同一个数据库里,很多一致性问题可以交给数据库处理。
拆成三个服务以后,情况可能变成:
Order Service -> Payment Service -> Inventory Service
三个服务各有自己的数据库。
这时已经没有一个简单的本地 COMMIT 能把三边一起提交。
你开始接触:
- Saga;
- 补偿事务;
- Outbox;
- 幂等消费;
- 最终一致性;
- 事件重复;
- 事件乱序;
- 消息投递失败。
微软官方文档说得很直接:多个微服务共同持久化一项业务变更时,完整操作通常很难继续保持传统意义上的 ACID 事务,需要接受和设计最终一致性。
这是分布式系统的价格。

图:Microsoft Azure Architecture Center 的微服务示例。注意服务之外还有消息总线、独立存储和 Kubernetes。真正的复杂度往往就在这些“服务以外”的东西里。
日志也不再是一份日志
单体出错时,运气好的话:
grep ERROR app.log
就能找到堆栈。
微服务里,一个用户请求可能经过:
Gateway
-> Auth
-> User
-> Permission
-> Workflow
-> NATS
-> Worker
你看到 Gateway 返回 500,只能说明 Gateway 最后没拿到正确结果。
真正的问题可能发生在六跳之外。
于是你需要:
- 结构化日志;
- 全局 trace ID;
- Metrics;
- Distributed Tracing;
- OpenTelemetry;
- 服务依赖图;
- 告警和 SLO。
微软最新的微服务 readiness assessment 把这些东西直接放进了采用微服务前后的评估清单:请求的 Trace Context 是否能跨同步和异步边界传播,日志、指标、Trace 能否按 trace ID 关联,依赖是否被监控。
如果这些基础能力完全没有,却先拆了几十个服务,事故发生以后通常会出现一种非常有仪式感的排障方式:
六个人同时打开六个终端,各自 docker logs -f。
测试会突然变贵
以前测试一个业务:
go test ./...
现在可能要先启动:
PostgreSQL
Redis
NATS
MinIO
Gateway
Auth
User
Workflow
Worker
...
然后你会发现服务 A 的单测全过,服务 B 的单测也全过,A 调 B 还是炸了。
原因可以是:
- 请求字段含义不同;
- API 版本不同;
- 错误码约定不同;
- protobuf 没同步;
- 超时策略不同;
- 数据已经发生 schema 漂移。
所以微服务通常会把 Contract Test、Integration Test、E2E、真实依赖测试的重要性一起拉高。
这也解释了为什么大型微服务项目的 verify 很容易越来越长。之前站里专门写过一篇:《项目写到后来,为什么跑一次 verify 要半小时》。
最危险的东西:分布式单体
我觉得这是小团队采用微服务时最值得警惕的结果。
表面上:
7 repositories
7 Docker images
7 services
实际上:
- 大家共享同一个数据库;
- 一个字段变更五个服务一起改;
- 一个服务不能脱离另外三个服务启动;
- 每次上线所有服务一起发;
- 测试必须完整启动全套环境;
- 一个公共库升级,全仓一起升级;
- 服务之间大量同步调用。
这时候你拥有的只是单体的耦合 + 分布式系统的故障模式。
代码边界切开了,业务边界没切开。
这种架构最大的成就,大概是把一次函数调用变成了一次网络请求。
如果两个服务总是一起修改、一起部署、一起扩容,那么它们为什么一定要是两个服务?
这个问题比“每个服务多少行代码”重要得多。
服务应该多小?
我不太喜欢用代码行数回答这个问题。
微软的文档也明确强调,比服务物理大小更重要的是内聚性和独立性。
更实用的判断方式是看几件事:
它有明确的业务能力吗?
“用户管理”可能有。
“UserControllerService”和“UserDatabaseService”通常只是把技术分层硬切成网络边界。
它能独立发布吗?
如果每次修改都必须协调三个服务同时发,边界很可能切错了。
它拥有自己的数据吗?
如果所有服务都直接读写同一组表,那么所谓服务自治很容易只剩 API 这一层。
它真的需要独立扩容或隔离故障吗?
如果答案长期都是“不需要”,进程边界带来的收益就值得重新算账。
有明确的人负责吗?
创建 notification-service 很容易。
两年以后还有谁负责升级它的依赖、处理漏洞、修告警,这才决定它是不是一个真正的服务。
这和上一篇 《我们是不是正在制造越来越多没人维护的软件?》 其实是同一个问题的另一面。
小团队,我更喜欢“模块化单体优先”
如果是一个新项目:
- 开发者 2~8 人;
- 业务边界还在不断变化;
- 用户规模还没真正验证;
- 发布频率没有形成团队瓶颈;
- 没有明显的独立扩缩容需求;
- 运维平台能力还不成熟;
我通常更倾向先把一个单体写干净。
注意,是模块化单体,不是所有代码塞进一个 service.go。
目录和依赖关系仍然可以按照领域切:
internal/
identity/
organization/
workflow/
asset/
notification/
模块之间通过清晰接口交互,数据库表也划好所有权。
等哪一天你真的发现:
notification 的流量和主业务差异很大;
workflow 已经有独立团队;
AI worker 必须跑 GPU;
某个模块发布频率严重拖累其他模块;
再把那个边界抽出去。
这时候拆服务是在解决已经存在的问题。
而不是提前解决一个想象中的“未来十亿用户”。
AWS 的 Well-Architected 指导里有一句很实际的意思:新产品冲首发和一个从第一天就明确要大规模扩展的系统,架构选择本来就不该一样。更小的服务能带来敏捷、扩展和故障隔离,同时也会增加延迟、调试难度和运维负担。
这个 trade-off 不会因为 Kubernetes 很流行就消失。
Kubernetes 也救不了错误的服务边界
Kubernetes 很强。
它可以帮你做:
- Deployment;
- Service Discovery;
- Load Balancing;
- Health Probe;
- Rolling Update;
- Autoscaling;
- Desired State Reconciliation。
但 Kubernetes 不知道:
order-service
和
payment-service
到底应该不应该拆开。
它也不知道两个服务为什么每天互相调用 50 次。
平台能管理分布式系统的运行,没法替你修正错误的领域边界。
把一个耦合严重的系统装进 Kubernetes,只会得到一个被自动编排得非常专业的耦合系统。
AI 又把这个问题放大了一次
现在生成一个新服务越来越便宜。
让 Agent 创建:
cmd/
internal/
Dockerfile
Helm Chart
OpenAPI
health endpoint
metrics
CI
可能几分钟就出来了。
于是架构图很容易迅速膨胀。
但真正昂贵的东西依然没变:
- 这个边界五年后是不是还合理;
- API 谁负责兼容;
- 数据归谁;
- 故障怎么恢复;
- 谁值班;
- 谁理解跨服务事务;
- 谁在一次线上故障后把调用链完整还原出来。
AI 降低的是创建服务的成本,没有同步降低拥有一个服务的长期成本。
这跟之前写的 《AI 把写代码变便宜以后,谁来替这些代码还债?》 很像。
我现在怎么判断一个项目要不要上微服务
如果让我看一个项目,我不会先问:
用不用 Kubernetes?
我通常先问下面这些:
1. 现在有多少支能够独立交付的团队?
2. 哪些业务模块真的需要独立发布?
3. 哪些模块资源模型明显不同?
4. 哪些故障必须被隔离?
5. 数据边界能不能清楚划分?
6. 跨服务事务到底有多少?
7. CI/CD、日志、Tracing、监控成熟了吗?
8. 谁拥有每一个服务?
如果前四个问题都答不上来,但已经准备部署 30 个微服务,我会建议先等等。
如果一个系统已经有十几支团队,一个单体每次发版要排队,某一块流量是其他模块的一百倍,不同业务需要完全不同的可靠性等级,那么继续坚持“一个程序最简单”,同样可能是在制造问题。
微服务没有天然的高级感。
单体也没有天然的落后感。
真正应该优化的是系统面对的现实约束。
最后
我越来越觉得,一个项目开始讨论微服务时,最有价值的问题不是:
“我们应该拆成几个服务?”
更应该先问:
“我们现在到底遇到了什么问题,值得为它引入一个分布式系统?”
如果这个问题没有答案,先别急着画那张满是六边形和箭头的架构图。
毕竟把一个简单问题做成分布式系统很容易。
把分布式系统长期维护好,完全是另一件事。
参考资料
- Microsoft Azure Architecture Center:Microservices architecture style
https://learn.microsoft.com/en-us/azure/architecture/guide/architecture-styles/microservices - Microsoft Azure Architecture Center:Microservices Assessment and Readiness
https://learn.microsoft.com/en-us/azure/architecture/guide/technology-choices/microservices-assessment - AWS:What are Microservices?
https://aws.amazon.com/microservices/ - AWS Well-Architected Framework:Choose how to segment your workload
https://docs.aws.amazon.com/wellarchitected/latest/framework/rel_service_architecture_monolith_soa_microservice.html - AWS Prescriptive Guidance:Service per team pattern
https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/service-per-team.html - Kubernetes:Services, Load Balancing, and Networking
https://kubernetes.io/docs/concepts/services-networking/
评论