前几年面试、都必须实战过微服务,好像不拆就落伍了。近两年风向反过来了:越来越多人开始反感,甚至有团队把拆出去的服务又合回来。
先看国内外几家对于微服务的态度
Stack Overflow:长期就是单体
很多人一听高并发就想拆服务。Stack Overflow 公共站点多年坚持 .NET 单体:大约 9 台 Web 机器,峰值约 6000 请求/秒、每月约 20 亿次请求。工程负责人说过大意是:拆服务通常是为了多团队并行、加快发布——这两件事他们在单体里并没有痛到必须拆。
它是流量已经很大,仍然选择单体。这比很多喊口号,提前浪费公司本地团队好太多了;因为流量大不一定必须微服务。
字节跳动:30 万个微服务之后,开始往回合并
国内最硬的例子是字节。基础架构团队在 QCon 2024 公开讲过:到 2023 年底,公司内部微服务超过 30 万,每个季度还在新增上万个,有的业务线人均要维护十几个服务。拆太碎之后,编解码、序列化、网络跳转、治理组件全变成税:链路变长、时延上去、机器也更费。
他们的办法叫合并编译:研发时仍按微服务拆仓库、拆团队,发布时把调用很密的几个服务编成一个二进制、跑在一个进程里,原来的 RPC 变成进程内调用。官方披露的量级是:合并后的服务超过 300 万核,CPU 配额省了 40 万核以上,接口时延按包大小能降 2~15 毫秒。
字节没有宣布全面退回单体。它说明的是另一件事:就算是养得起微服务平台的大厂,拆过了头也得往回合。 中小团队没有30万个服务,但人均十几个仓库实在也维护不过来。
阿里:把中台变薄,承认先抽象、先共享会拖业务
2015年前后阿里提大中台、小前台,国内一堆公司跟着拆中台、拆微服务。2021 年张勇在内网明确说:对当时的中台不满意,业务发展太慢,要把中台变薄,变得敏捷。后来组织上也把大中台拆开,能力留给前台。
中台不等于微服务,但国内这两件事经常被绑着卖:先抽共享服务、先拆领域、前台来申请能力。结果很多团队不是更快,而是改个字段要等中台排期。阿里自己把中台做薄,不是否定服务化,是承认 过度抽象、过度共享,会把交付拉长。
Shopify:考虑过微服务,但最后选模块化单体
Shopify 核心电商代码体量极大。他们评估过微服务,否决理由是:真正痛的是模块边界不清,不是没有拆成多个进程。他们要的是代码隔离、依赖可见,同时保留一次构建、一次发布。这就是后面会提到的模块化单体。
所以,大厂都在为自己的约束做选择。那我们中小团队,更没必要把网关+注册中心+链路追踪+分布式事务等等当成标配。
核心原因
单体把一次请求里该在一起的事留在一起了。
查数据:一次 Join,顶三次远程调用
单体里查一张订单详情很常见:订单头、明细、客户、运单,数据库一次就能拼出来。拆成订单服务、客户服务、运单服务之后,同一个页面往往要打三次接口,再在内存里拼。每次多一次网络、一次序列化、一次失败可能。客户服务一超时,详情页就缺一块;分页、排序、模糊搜一旦跨服务,更麻烦,要么自己拼,要么再上一套搜索。
事务:进程内提交,不用考虑分布式事务
单体里「创建订单 + 扣库存 + 生成运单」就是数据库事务:成功就一起成功,失败就一起回滚。这是关系型数据库最擅长的事。
一拆服务,本地事务没了,只能上最终一致(实现Saga,TCC等分布式事务)
排障和交付:一个进程跟完,改一处发一版
单体出问题:看这一次请求的日志,断点从 Controller 跟到仓储,本地F5就能复现。
微服务出问题:请求 ID 要贯穿网关、服务 A、服务 B、队列、再回 A。少打一条日志就断链;本地要起一堆容器,有人环境能跑、有人跑不起来。线上再叠加「这个服务是上个迭代的版本,那个服务刚发了不兼容字段」。
发布也一样。单体是一次构建、一次发布、一次回滚。微服务是:接口先协商、兼容期、灰度顺序、谁先发谁后发。一个字段改名,可能同时改三个仓库、三套 DTO、两份文档。
开发周期被拉长,往往不是写业务慢了,是对齐和等待变多了。
维护和沟通:人少时,拆服务等于把沟通写进架构
项目简单时,维护成本差最明显。一套解决方案、一套配置、一套部署脚本;新人 clone 下来就能跑。拆开之后,每个服务都有自己的依赖、配置、健康检查、资源限额,仓库数量线性涨,心智负担一起涨。
两个团队各守一个服务,一个改字段类型、一个没跟上,就是生产事故。一个团队守八个服务,那就是自己和自己开会。
字节人均十几个服务、阿里中台要排期,本质一样:服务数量涨上去之后,运营和协同开销先把研发节奏和心态搞崩。
基础设施是有成本的
认真跑微服务,通常还要准备:
- API 网关
- 服务发现 / 配置中心
- 链路追踪、集中日志、指标
- 消息队列和死信
- 容器编排、资源隔离
- 分布式限流、熔断、超时、重试
每一项都有价值,每一项都要人值班。字节那个量级里,光是服务之间的序列化和网络跳转,就能吃掉几十万核。
还有隐性成本:机器变多、调用变碎、云账单变难看。不是微服务一定贵,是为了拆而拆,单位业务量的固定开销会偏高。
那微服务是不是不用学了?
微服务依然是可选的架构设计,而不是是默认必须上微服务。
这些情况,拆仍然合理:
- 组织已经按业务切开:支付一组人、履约一组人、增长一组人,发布节奏天然不同;
- 负载差一个数量级:转码、报表、爬虫把下单接口拖死,值得独立扩容;
- 故障必须隔离:验证码、第三方回调挂了,不能把主站一起带走;
- 边界已经稳定:两块业务很少一起改,接口一年难得变一次;
- 平台和工具已经有了:网关、追踪、发布、值班不是从零开始攒。
Stack Overflow 自己也说过:团队变大、要独立演进时,会再评估哪些模块该拆出去。这才是正常顺序——先痛,再拆;不是先拆,再找痛。
更稳的中间态:模块化单体
很多人口里讨厌的不是「一个进程」,是「一个大泥球」:项目互相引用、表谁都能改、改仓库却碰到订单模块代码。
这和 Shopify 的判断一样:要的是边界,不是分布式。
模块化单体仍然一次部署,但按业务切开:订单、库存、运单各管各的,入口只有一个。模块之间走明确的接口或领域事件,禁止跨模块直接改对方的表。等某一块真的成为独立团队或独立瓶颈,再把这个模块提成服务——那时你拆的是已经隔离好的一块,而不是从泥球里生撕。
.NET 很适合这条路:一个解决方案里按模块分项目,需要时再把某个模块换成独立站点,调用从进程内变成HTTP或队列,业务不用推倒重来。
吐槽
- 我见过一些公司用户没多少,订单没多少,微服务十几个;
- 有些公司要在子服务加个字段各种排期(不同研发组),严重拖慢交付周期;
- 微服务排查问题+甩锅真的一流。
最后,单体不比微服务差,微服务也没有更高级。架构不是从众、潮流,是按眼下的业务、以及能看见的下一步,提前做的布局。