知识点深化 · 微服务实战
微服务实战:服务拆分、服务间通信、分布式事务、服务治理
单体应用拆成微服务不是"把代码分成几个文件夹"那么简单。这一页讲透 FDE 在客户现场真正会用到的微服务工程:按业务域怎么拆、服务间同步调用和异步消息怎么选、分布式一致性怎么兜底、注册中心和网关怎么配、分布式追踪怎么搭。
① 小白第一课怎么学(5 步走,约 100 分钟)
先抓住"按业务拆"这个核心,微服务不是目的,是手段。
1理解为什么拆(15 分钟)
读②③:单体的痛 vs 微服务的代价。
2学拆分原则(20 分钟)
读④:按业务域拆,数据库 per 服务。
3通信方式(25 分钟)
同步 HTTP vs 异步 MQ,各自适用场景。
4治理三件套(25 分钟)
注册中心、网关、分布式追踪。
5刷题巩固(15 分钟)
做⑥⑦⑩。
本课小目标学完你要能:① 判断什么时候该拆微服务;② 按业务域拆出合理的服务边界;③ 选对同步调用还是异步消息;④ 用本地消息表解决分布式一致性。
② 一图看懂:微服务架构全景
读法:网关是统一入口,业务服务按业务域拆、各自有库,注册中心管寻址,MQ 做异步解耦,追踪管排障。
③ 本质直觉:微服务就是"按业务分公司"
想象一家大公司。一开始所有人在一个办公室(单体),大家都能用所有资源。人多了之后开始乱:互相干扰、发布慢、沟通成本高。
微服务就是把公司拆成几个独立部门:用户部、订单部、财务部。每个部门有自己的数据库(文件柜),部门之间打电话(API)或者发邮件(MQ)沟通。
部门之间不能互相翻文件柜——这就是"数据库 per 服务"。要拿数据得通过对方的 API,不能直连数据库。这样一个部门崩了不会拖垮全公司。
代价是:部门之间沟通要走流程,跨部门事情慢。但部门内部是高效的。
什么时候不该拆团队就 3-5 人、业务还在快速验证期、日活不高——单体加模块化分层比微服务划算。微服务是"规模到了"之后的选择,不是政治正确。
④ 完整体系:拆分原则、通信方式、一致性、治理
服务拆分对照表
| 维度 | 正确做法 | 错误做法 |
| 拆分依据 | 按业务域(DDD 限界上下文) | 按技术层(controller/service/dao) |
| 数据库 | 一个服务一个 schema | 多个服务共享一个库 |
| 服务粒度 | 先粗后细,逐步拆 | 一次拆成几十个超细服务 |
| 依赖方向 | 单向依赖,底层不依赖上层 | 循环依赖 |
同步 vs 异步通信
| 方式 | 技术 | 优点 | 缺点 | 适用场景 |
| 同步 HTTP | REST/gRPC | 简单直接、立刻拿结果 | 耦合高、下游挂了跟着挂 | 需要实时结果的核心链路 |
| 异步 MQ | Kafka/RabbitMQ | 解耦、削峰、可重试 | 调试难、最终一致 | 通知、日志、非核心路径 |
分布式一致性方案
| 方案 | 原理 | 适用场景 |
| 本地消息表 | 本地事务里写业务+消息,后台 relay 发 MQ | 最常用,性价比最高 |
| TCC | Try-Confirm-Cancel 三步 | 资金类强一致,成本高 |
| Saga | 一串本地事务+反向补偿 | 长流程业务 |
本地消息表代码骨架
# 同一个本地事务里写业务数据 + outbox 消息
BEGIN;
INSERT INTO orders (id, user_id, total) VALUES (123, 1, 99);
INSERT INTO outbox (topic, payload) VALUES ('order.events', '{"order_id":123}');
COMMIT;
-- 后台任务:扫 outbox 发 MQ,发完标记
UPDATE outbox SET sent=true WHERE id=?;
服务治理三件套
| 组件 | 作用 | 常见实现 |
| 注册中心 | 服务启动注册自己地址,调用方发现地址 | Nacos/Consul/etcd |
| API 网关 | 统一入口:路由、鉴权、限流 | Nginx/Kong/APISIX |
| 分布式追踪 | trace_id 透传,看一个请求跨了哪些服务 | Jaeger/OpenTelemetry |
⑤ 用法场景与典型例题
例1(拆分判断)一个电商单体有用户、商品、购物车、订单、支付、库存、通知。你怎么拆?
按业务域拆,先粗后细。
第一刀:用户服务、商品服务、订单服务(核心三域)。
第二刀:支付服务、库存服务(独立逻辑重)。
第三刀:通知服务(纯异步,最容易拆)。
购物车先跟订单放一起,别一次拆太碎。
答案:按业务边界逐步拆,不要按技术层拆。
例2(同步异步选择)下单后要发短信通知用户,用同步还是异步?
看是否在核心路径上。
发短信不影响下单主流程,挂了也不影响用户体验。
应该用异步消息:下单成功发一条 MQ 消息,通知服务消费发短信。
答案:非核心路径用异步,解耦+削峰+不拖慢主流程。
例3(分布式一致性)下单要同时写订单表和扣库存,怎么保证?
跨服务事务,用最终一致方案。
推荐本地消息表:订单服务在本地事务里写订单 + 写 outbox 消息,后台 relay 发 MQ,库存服务消费消息扣减。
扣减失败就走补偿(发退款消息)。
不要强上分布式事务(2PC),性能差还复杂。
答案:本地消息表 + MQ,最终一致即可。
⑥ 高频错误诊断(4 条)
错误 1:按技术层拆服务把 controller 层拆一个服务、service 层拆一个——这是最常见也最蠢的拆法。每次改业务要跨三个服务。正确做法是按业务域拆:订单服务管所有订单相关的代码。
错误 2:多个服务共享一个数据库看似方便,实际耦合死了。改表结构要协调所有服务,跟单体没区别。一个服务独占一个 schema,别的服务只能通过 API 拿数据。
错误 3:同步调用不设超时下游服务卡住,你的线程被占满,整个服务雪崩。所有 HTTP 调用必须设 timeout,再加重试和熔断。
错误 4:拆太细,几十个微服务运维成本爆炸。一个请求跨 10 个服务,排障要疯。先粗后细,有真实痛点了再拆。
⑦ 考点真题演练(4 题)
考点分布
| 考法 | 出题形式 | 应对 |
| 拆分原则 | 判断拆法对不对 | 按业务域、数据库 per 服务 |
| 通信选择 | 场景选同步/异步 | 核心同步、非核心异步 |
| 一致性 | 跨服务事务怎么处理 | 本地消息表最常用 |
| 治理 | 注册中心/网关作用 | 服务发现、统一入口 |
真题基础1. 微服务应该按什么拆分?
真题中档2. 下单后发通知短信,用什么通信方式?
真题中档3. 跨服务数据一致性,FDE 最常用的方案是?
真题拔高4. 服务 A 调服务 B 超时了,下列哪个处理最不恰当?
⑧ 必背知识点卡
拆分:按业务域拆,不按技术层 一个服务一个库
通信:核心链路同步 HTTP,非核心路径异步 MQ 同步必设超时
一致性:本地消息表最常用,别硬上 2PC 最终一致就够
治理:注册中心管寻址、网关管入口、追踪管排障 三件套
粒度:先粗后细,别一次拆几十个 运维成本爆炸
依赖:单向依赖,不能循环 底层不依赖上层
⑨ 应用输出:设计一个简单的微服务拆分方案
场景:一个内容平台,有用户、文章、评论、点赞、通知
① 识别业务域:用户域(注册/登录/资料)、内容域(文章发布/编辑)、互动域(评论/点赞)、通知域(消息推送)。
② 第一版拆 3 个服务:用户服务、内容服务(文章+评论先放一起)、通知服务。点赞先跟内容放一起,不用单独拆。
③ 数据库:每个服务独占一个 schema,用户服务管 users 表,内容服务管 articles/comments 表。
④ 通信:文章发布后发 MQ 消息,通知服务消费后给关注者推送——异步解耦。文章详情页需要用户昵称,同步 HTTP 调用户服务拿。
⑤ 治理:Nacos 做注册中心,Nginx 做网关,OpenTelemetry 做链路追踪。
口述设计思路"先按业务域粗拆三个服务,各自有独立数据库;核心数据查询走同步 API,通知类走异步 MQ;注册中心管服务发现,网关统一入口,追踪排障。"
⑩ 分层练习 15 题(基础 5 + 中档 5 + 拔高 5)
▍基础 5 题
基础1微服务按什么拆分?
业务域(DDD 限界上下文),不按技术层。
基础2每个微服务有自己的数据库吗?
有。数据库 per 服务,别的服务不能直连它的表。
基础3注册中心是干什么的?
服务启动时注册自己的地址,调用方从中发现可用服务列表。解决"服务 IP 动态变"的问题。
基础4API 网关的作用?
统一入口:路由转发、鉴权、限流、日志。业务服务不用关心这些横切关注点。
基础5同步调用为什么要设超时?
防止下游卡住拖死整个服务(线程池耗尽、雪崩)。必须设 timeout,不能无限等。
▍中档 5 题
中档6什么时候该用异步 MQ 而不是同步 HTTP?
非核心路径、不需要立刻返回结果的场景(如发通知、写日志、发邮件)。解耦+削峰+失败可重试。
中档7本地消息表解决什么问题?
解决"本地事务和发消息的原子性"问题。同一个本地事务里写业务数据+outbox 消息,保证要么都成功要么都失败。
中档8什么是循环依赖?为什么要避免?
A 调 B、B 又调 A。导致发版顺序排不出来、改一处两边都要改。要建单向依赖方向图,底层不依赖上层。
中档9分布式追踪解决什么问题?
一个请求跨多个服务,日志散在多台机器。trace_id 透传+可视化链路,能定位慢在哪个服务哪一步。
中档10微服务一定比单体好吗?
不是。小团队、业务简单时单体更高效。微服务带来的分布式成本,只有规模上去后才划算。
▍拔高 5 题
拔高11TCC 和本地消息表怎么选?
大多数业务用本地消息表(简单可靠);资金类强一致要求高的才上 TCC(成本高、开发复杂)。
拔高12服务 A 调 B 失败了,重试要注意什么?
只对幂等操作重试;指数退避(别立刻重试打爆);设最大重试次数;最终失败要降级兜底。
拔高13为什么多个服务不能共享一个数据库?
耦合死了:改表结构要协调所有服务,跟单体没区别。服务自治的底线就是自己的库自己管。
拔高14怎么避免拆太细?
先粗后细:一开始合并相关功能,有真实痛点(独立扩缩容、发布互相影响)了再拆。不要为了拆而拆。
拔高15一个请求跨 5 个服务超时了,怎么定位?
用分布式追踪(Jaeger/OTel)看 trace 里每个 span 的耗时,找到最慢的那个服务,再去查那个服务的日志和监控。
⑪ 记忆口诀 + 7 天复习计划
三句口诀
① 按业务拆服务,一个服务一个库。
② 核心同步设超时,非核心异步走 MQ。
③ 一致性靠本地消息表,治理三件套别少。
| 天 | 任务 | 自检 |
| 第 1 天 | 读②③,画一遍微服务全景图 | 能说清每个组件作用 |
| 第 2 天 | 背拆分原则 + 做基础 1-5 | 基础全对 |
| 第 3 天 | 同步 vs 异步场景题 | 选得对 |
| 第 4 天 | 做中档 6-10,理解本地消息表 | 能画 outbox 流程图 |
| 第 5 天 | 做拔高 11-15 + 真题 4 题 | 会设计拆分方案 |
| 第 6-7 天 | 口述一个微服务架构设计,默写组件清单 | 不看资料全默对 |
← 返回 FDE 培养总览