第12章 微服务的痛:用实际经历告诉你它有多少陷阱
第3部分主要讲解了基于常见组件的微服务场景,因为目前已经有了一些比较流行的开源组件,所以只需要清楚组件的原理即可。从这一章开始,将进入第4部分——微服务进阶场景实战。
在介绍业务场景之前,先来谈谈微服务的概念和优缺点。

12.1 单体式架构 VS 微服务架构
为了快速理解单体式架构与微服务架构之间的区别,先来看一个新零售系统的例子。
某门店(门店分为自营店和加盟店)计划研发一款新零售系统进行商品售卖,它需要包含订单、营销、商品、门店、会员、加盟商等功能模块。
单体式架构
在搭建新零售系统架构时,如果使用单体式架构进行设计:
- 所有模块的代码存放在一个应用中
- 所有模块的数据存放在一个数据库中
在这种架构模式下,当业务功能增加到一定程度时,只要稍微有点小改动,就有可能影响整个应用的其他功能。虽然每次系统崩溃后都会进行复盘,后期需要 Code Review、合理设计、仔细评估风险、共同评审方案,但是问题还是会发生。
因此,随着风险控制流程的复杂化,代码发布的频率越来越低,最终导致系统无法迭代,而其他公司交付新功能的效率却是它的 10 倍以上。
微服务架构
面对这种情况,必须把各个模块的代码进行拆分,以免相互影响。于是把单体式架构拆分为微服务架构:
- 一个应用被拆分成了 6 个应用
- 分别负责订单、营销、商品、门店、会员、加盟商等相关的业务逻辑
- 每个模块的数据分别存放在不同数据库中
- 各个应用之间如果彼此存在依赖关系,可以通过接口、消息、共享缓存、数据库同步等方式来解决
12.2 微服务的好处
将单体式架构迁移到微服务架构后,确实带来了诸多便利:
| 优势 | 说明 |
|---|---|
| 易于扩展 | 某个模块的服务器处理能力不足时,在该模块所处应用的服务器中增加节点即可 |
| 发布简单 | 只需要保证对外契约不变即可,发布过程变得非常简单 |
| 技术异构 | 各个服务之间相互独立、互不影响,内部可以使用各自不同的语言或框架 |
| 便于重构 | 把模块间的影响进行了隔离,大大增加了重构的灵活性 |
12.3 微服务的痛点
在产品研发过程中,引入一种技术来解决一个业务问题并不难,难的是能否合理评估技术风险,这个观点对微服务同样适用。

12.3.1 痛点:微服务职责划分
微服务的难点在于无法对一些特定职责进行清晰划分,比如某个特定职责应该归属于服务 A 还是服务 B?
划分原则
-
根据存放主要数据的服务所在进行划分
- 根据商品 ID 找出商品信息的接口 → 放在商品服务中
- 获取单个用户的所有订单 → 放在订单服务中
-
业务逻辑服务归属与业务人员的划分可能存在关系
- 各个门店的商品库存由该门店的运营人员管理 → 放在门店系统中
-
业务逻辑服务归属与产品人员的划分可能存在关系
- 由商品系统的产品经理负责 → 放在商品服务中
- 由门店的产品经理负责 → 放在门店服务中
-
业务逻辑服务归属与工期可能存在关系
- 再优雅的设计也抵不过业务部门要求的上线时间压力
-
业务逻辑服务归属还可能与组织架构存在关系(康威定律)
设计系统的组织在设计系统时,会设计出基于这些组织的沟通结构的系统。
在现实场景中,微服务职责的划分会受太多人为因素的影响,这也是为什么现在关于服务职责划分原则的相关资料不太多的原因。
12.3.2 痛点:微服务粒度拆分
微服务还有一个痛点,就是服务太多。
实际案例
以加盟商系统为例:
- 最初只有登录和信息管理功能 → 一个服务即可
- 随着业务开展,需要增加财务功能、员工管理、返点、子门店管理等
问题:微服务的粒度到底拆分到多细比较合适?
影响粒度的因素
- 团队规模原则:根据新的微服务的大小,安排 3~4 人设计即可
- 绩效因素:开发人员在阐述个人工作量时偶尔会提微服务数,潜意识里喜欢做微服务
- 结果:微服务就会越来越多,甚至出现人均 5 个微服务数的情况
微服务的粒度大小控制在什么范围比较合适?这就是一个痛点,因为没有确切的答案。
12.3.3 痛点:没人知道系统整体架构的全貌
每隔几个月或半年,领导就会让汇报一下每个部门的微服务数量、公司微服务总数量、每个微服务都用来做什么等情况。
"几百个微服务?系统这么复杂了吗?谁知道所有系统的全貌?如果出现问题,你们如何快速定位问题?"
在使用微服务的公司后,很难找到了解微服务系统架构全貌的人员,只要熟悉自己负责的部分即可,如果出现问题就临时学习一下相关系统。
12.3.4 痛点:重复代码多
没有使用微服务的公司会把所有的代码放在同一个工程中,如果发现某些代码可以重复使用,把这些代码抽取出来存放在 Common 包中即可。
但是这种代码设计在微服务中经常会出现问题:
| 步骤 | 问题 |
|---|---|
| 团队 A 做了一个日志自动埋点功能 | 其他团队想拿来用 |
| 团队 B 使用后出现 JAR 版本冲突 | 埋点团队需要重新设计兼容版本 |
| 团队 C 又汇报 JAR 版本冲突 | 埋点团队放弃维护,直接告知其他团队自己复制修改 |
| 统一 JAR 版本项目立项 | 因紧急业务需求搁置 |
结论:维护这些不多的重复代码总比统一排期做重构、统一评审 JAR 版本的成本低得多。
12.3.5 痛点:耗费更多服务器资源
某公司原来使用单体式架构,一共部署了 5 台服务器,后来拆分成了 6 个微服务:
| 架构 | 服务器数量 | 说明 |
|---|---|---|
| 单体式 | 5 台 | 原始架构 |
| 微服务 | 15 台 | 每个服务 2 节点 + 网关层 2 台 |
业务没有变,流量没有变,代码逻辑改动也不大,却多出了 9 台服务器。

12.3.6 痛点:分布式事务
分布式事务这个痛点对于微服务来说,简直就是地狱。
实际案例:下单流程
原本的下单流程:
插入订单 → 修改库存 → 插入交易单 → 插入财务应收款单 → 返回结果
单体式架构:只需要把上面的下单流程包含在一个事务里就可以了。
微服务架构:因为这几个流程分别存放在不同的服务中,需要考虑:
- 某个流程出错是否需要将数据全部回滚?
- 是否选择统一不回滚,失败就重试?
- 如果做成异步,会不会出现时间超时?
针对这种情况,在大部分场景下不考虑回滚和重试,只考虑写"Happy Path",如果报错就记录异常日志,再线下手工处理。
结果是:机房网络抖动时,数据更新总是出现异常,比如上游数据更新了,下游数据没有更新,出现了错误数据。
12.3.7 痛点:服务之间的依赖
在设计类时,往往需要遵循类与类之间不可循环依赖的原则,因此最终设计出来的类关系是层次分明的结构。
但是微服务的现实情况:
- 商品系统依赖门店系统(门店类型设置价格)
- 门店系统依赖商品系统(门店库存需要商品信息)
- 财务系统需要依赖订单信息、会员信息和门店信息
最终,服务之间的依赖关系变成千丝万缕、难以理清的架构——"你中有我,我中有你"。
两次架构经历
-
重构评估影响面让各个团队鸡飞狗跳
- 需要根据全链路日志系统找到所有上游服务
- 评估后发现大半的微服务都会受到影响
- 很多团队不得不一起通宵达旦地做回归测试
-
为了不影响其他团队,出现了很多版本
- 新的代码直接调用 V2 版本,旧的代码继续调用 V1 版本
- 服务数量出现暴涨,新旧版本并存
- 维护起来更痛苦
这个问题的解决方案将在第15章进行讲解。
12.3.8 痛点:联调的痛苦

以往的需求排期:
需求评审时间 → 开发完成时间 → 测试完成时间 → 上线时间
迁移到微服务后:
需求评审时间 → 接口设计时间 → 开发完成时间 → 联调完成时间 → 测试完成时间 → 上线时间
联调中的常见对话
调用方:"addXXX的接口怎么样了?"
被调用方:"好了,你可以调调看。"
调用方:"不行啊,返回了404。"
被调用方:"哎呀,环境部署错了,稍等一下。"
...
调用方:"addXXX的接口需要增加一个修改时间字段,你帮我加一下。"
被调用方:"可以,不过我正忙着另外一个项目,要不明天给你?"
调用方:"别啊,今天必须联调完。"
被调用方:"那我晚上赶一赶,9点给你行吗?"
在做项目时最麻烦的事情之一就是协调时间,因为它不可控。
关于这个痛点,将在第16章中给出解决方案。
12.3.9 痛点:部署上的难题
使用单体式架构时,每个开发人员都想在本地把整个系统部署完后再调试。
迁移到微服务后,项目经常涉及 10 个以上的微服务:
- 内存很可能不够
- 几乎没有开发人员会熟悉所有微服务的部署
解决方案:专门建立一套测试环境供开发人员进行联调。
测试环境的问题
| 问题 | 说明 |
|---|---|
| 联调环境的数据缺漏非常多 | 数据是开发数据,单个服务中的数据不具备完整性 |
| 服务调用错误 | 经常有人调用了错误的服务节点 |
| 联调环境极度不稳定 | 开发人员常常需要对联调中的服务进行部署 |
这就是第17章将要分享的内容。
12.4 小结

微服务的9个痛点
| 痛点 | 核心问题 |
|---|---|
| 职责划分 | 受太多人为因素影响,没有确切标准 |
| 粒度拆分 | 服务太多,粒度难以控制 |
| 架构全貌 | 没人知道系统整体架构 |
| 重复代码 | JAR版本冲突,维护成本高 |
| 服务器资源 | 微服务比单体式消耗更多服务器 |
| 分布式事务 | 数据一致性问题是地狱级难度 |
| 服务依赖 | "你中有我,我中有你" |
| 联调痛苦 | 协调时间不可控 |
| 部署难题 | 测试环境不稳定 |
为什么还要使用微服务?
微服务的优势讲了 5 点,而痛点讲了 9 点,为什么还要使用微服务?
如果使用单体式架构的话,随着业务的复杂化,将会出现无论怎么加人都无法迭代的情况。
而如果使用微服务,虽然它存在很多问题,但是至少可以通过增加人力的方式来保持迭代。
原因就这么简单,跟那些痛点无关。
程序员喜欢用新技术,但新技术层出不穷。对于新技术,要有敬畏心,除了知道它的优点,也要了解它的缺点。
微服务架构的痛点介绍完了,接下来开始讲一些进阶的微服务实战场景,看看如何解决本章提到的这些痛点。