为什么我不再迷信微服务

作者:秃头码农 发布时间: 2026-04-12 阅读量:42 评论数:0

先说结论:过去一年,我把手上一个由 9 个微服务组成的系统,合并回了 3 个。上线三个月,P99 从 1.2 秒降到 380 毫秒,故障率下降大概六成,团队开发一个需求的平均周期从 5 天缩短到 2 天。

我不是要否定微服务,而是想说清楚一件事:我们当初拆分的理由,几乎没有一条站得住脚。

我们当初是怎么拆的

三年前那个系统还是一个单体。有一次线上事故,一个报表查询把数据库拖垮,影响了核心下单。复盘会上结论是「耦合太重,要拆」。于是我们按业务名词拆:用户、商品、订单、库存、支付、通知、报表、搜索、配置。九个服务,听起来很专业。

问题是,当时整个后端团队只有 6 个人。

然后发生了什么

一次调用变成了七跳。 用户点一次「提交订单」,请求依次经过网关、订单、用户、商品、库存、支付、通知。每一跳都有序列化、网络往返、连接池等待。我们做过一次链路追踪的统计,真正的业务计算大概占总耗时的 18%,剩下 82% 花在了服务之间互相说话上。

一个字段要改四个仓库。 商品加一个「预售标记」字段,要改商品服务的模型、订单服务的 DTO、库存服务的判断逻辑、还有网关的字段透传白名单。四个仓库、四个 PR、四次评审、四次发版,还得排发版顺序。这个需求本身写代码不到两小时,走完流程用了三天。

本地起不来了。 新人入职第一天的任务是「把环境跑起来」,结果要起 9 个服务加 MySQL、Redis、消息队列,笔记本风扇狂转。后来我们不得不专门维护一套开发环境的编排脚本,这套脚本本身又成了需要人维护的东西。

分布式事务成了日常。 下单要扣库存、创建订单、冻结优惠券。在单体里这是一个数据库事务,三行代码。拆开之后我们上了消息队列做最终一致,写了补偿任务、对账任务、幂等表。这套东西加起来两千多行,全是为了解决「我们自己制造出来的问题」。

我现在的看法

微服务解决的核心问题是组织协作,不是技术性能。当你有 80 个工程师,分成 10 个小组,每组想独立发版、独立选型、独立扩容,微服务是必须的——因为单体仓库里 80 个人天天冲突,谁也别想安心发版。

但当你只有 6 个人的时候,你根本没有协作瓶颈。你有的是「一个人要在四个仓库之间来回跳」的瓶颈。这时候拆分带来的全是成本,收益一分没有。

至于当初那次事故——报表查询拖垮数据库——正确的解法是给报表配一个只读从库,或者干脆加个查询超时和限流。这是一个资源隔离问题,不是架构问题。我们用了三年时间和一整套分布式基础设施,去解决一个本来加两行配置就能解决的问题。

合并之后保留了什么

我不是原教旨的单体党。这次合并后我们留了 3 个服务:核心业务、异步任务、对外开放接口。划分依据不是业务名词,而是运维特征

  • 核心业务对延迟敏感,要快速扩容;
  • 异步任务吃 CPU 和内存,跑得慢没关系,但不能影响别人;
  • 对外接口面向公网,安全等级和限流策略完全不同。

这三种东西放在一个进程里确实会互相拖累,拆开是有实际收益的。而「用户」和「商品」放一起有什么坏处?没有。它们的调用频率、资源画像、发布节奏都一样。

一个我常用的判断标准

要不要把某段代码拆成独立服务,我现在只问一个问题:它是否需要和主体不同的发布节奏、扩容策略或故障域?

如果三个都不是,那它就应该是主体里的一个模块、一个包、一个目录。模块边界可以通过代码规范和评审来保证,不需要用网络调用来强制。用 RPC 来划分模块边界,就像用锁门来提醒自己别忘带钥匙——有效,但代价太大了。

评论