写在前面
前三篇我一直在"劝退"过早微服务化,不是反对微服务,是想让你想清楚再拆。这一篇就把账算明白:拆成微服务之后,你到底要为哪些隐性成本买单。
我把这些成本叫做**“分布式税”**——单体里免费的东西,到了分布式环境,每一项都要你自己花人、花钱、花时间重新建起来。
一、什么叫"分布式税"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 单体里(进程内)免费的能力:
- 函数调用 = 直接 new、直接调,纳秒级
- 强一致性 = 一个数据库事务搞定
- 配置 = 读本地配置文件
- 日志 = 写同一个文件
- 鉴权 = 一个进程内的中间件
- 故障传播 = 进程挂了,全挂(简单粗暴)
微服务里(跨网络)每一项都要重新建:
- 函数调用 → 网络调用(毫秒级、会超时、会丢包)
- 强一致 → 分布式事务(Saga / TCC / 最终一致)
- 配置 → 配置中心(集中下发、动态刷新)
- 日志 → 日志聚合(收集到统一存储)
- 鉴权 → 每个服务都要验 token
- 故障 → 一个挂了,可能雪崩倒一片
这些"重建",就是分布式税。
|
二、第一笔税:网络根本不可靠
这是分布式系统一切痛苦的根源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| 进程内调用 vs 网络调用:
进程内调用:
✓ 几乎不会失败(除非进程崩)
✓ 纳秒~微秒级
✓ 没有序列化开销
网络调用:
✗ 会超时(对方慢、网络抖动)
✗ 会丢包、会重试、会乱序
✗ 毫秒级起步,还要序列化
✗ "超时"最可怕——不知道对方到底执行了没有
八大谬误(Peter Deutsch):
1. 网络是可靠的 ❌
2. 延迟为零 ❌
3. 带宽是无限的 ❌
4. 网络是安全的 ❌
5. 拓扑不会变化 ❌
6. 只有一个管理员 ❌
7. 传输成本为零 ❌
8. 网络是同构的 ❌
|
代价:每一次跨服务调用,都要处理重试、超时、幂等、降级。单体里一个 try-catch 搞定的,微服务里是一整套弹性策略。
网络为什么不可靠、CAP 为什么成立——我在《分布式系统学习笔记(一):CAP 与一致性》里讲过底子。这里只说工程后果。
三、第二笔税:服务发现与配置
单体里,所有代码在一个进程,互相调函数即可。微服务里,“找谁"和"用什么配置"成了问题。
1
2
3
4
5
6
7
8
9
10
11
| 单体:函数地址 = 编译期固定
微服务:服务实例的 IP/端口是动态的(容器漂移、弹性扩缩)
必须自建的能力:
- 服务注册与发现(谁在线、在哪)
常见:Consul / Nacos / etcd / K8s Service / Eureka
- 配置中心(配置不再散落各服务)
常见:Nacos / Apollo / Consul KV / K8s ConfigMap
- 动态刷新(改配置不重启)
这些都是单体里"不存在"的基础设施。
|
四、第三笔税:数据一致性
这是最重的一笔税,下一篇会专门展开,这里先列账:
1
2
3
4
5
6
7
8
9
10
11
| 单体:一个事务保证 ACID
微服务:每个服务一个库,跨库没有 ACID
你必须自建:
- 分布式事务方案(Saga、TCC、Outbox 模式)
- 最终一致性补偿机制
- 幂等性保证(重试导致的重复执行)
- 对账机制(数据不一致时的人工/自动核对)
详见我写的《分布式系统学习笔记(四):分布式事务》。
本系列第五篇会讲它怎么在数据架构上落地。
|
五、第四笔税:可观测性
单体里,一个请求的处理在一个进程内,看一个日志文件就懂了。微服务里,一个请求要经过 5 个服务,出问题你怎么定位?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| 必须自建"微服务的神经系统":
- 链路追踪(Trace)
给每个请求一个 traceId,跨服务透传
常见:OpenTelemetry / Jaeger / Zipkin / SkyWalking
- 指标监控(Metrics)
每个服务的 QPS、延迟、错误率
常见:Prometheus + Grafana
- 日志聚合(Logs)
所有服务的日志收到一处,按 traceId 串联
常见:ELK / Loki
没有这三件套,微服务一旦出问题 = 黑盒,只能玄学排查。
第七篇会专门讲可观测性。
|
六、第五笔税:可靠性与弹性
1
2
3
4
5
6
7
8
9
10
11
12
13
| 单体里:一个函数失败 → 抛异常,调用方决定怎么办
微服务里:一个服务失败 → 故障会沿调用链放大,可能雪崩
必须自建:
- 超时(Timeout)—— 别傻等
- 重试(Retry)—— 配合幂等
- 熔断(Circuit Breaker)—— 别打已经挂的服务
- 限流(Rate Limit)—— 别被流量压垮
- 降级(Fallback)—— 给个兜底响应
- 舱壁隔离(Bulkhead)—— 别让一个慢调用拖垮线程池
.NET 生态:Polly(这套东西几乎成了标配)
本系列第八篇落地时会用上。
|
1
2
3
4
5
| 雪崩示意:
服务 A 依赖 B,B 依赖 C
C 慢了 → B 的线程被占满 → B 也慢 → A 的线程被占满 → A 也挂
一个底层小故障,逐层放大,拖垮整条链路。
熔断 + 舱壁就是用来切断这种放大效应的。
|
七、第六笔税:运维与部署
1
2
3
4
5
6
7
8
9
10
11
| 单体运维:1 个应用 × N 台机器
微服务运维:M 个服务 × N 个实例 × 动态变化
- 需要容器化(Docker)+ 编排(K8s)
见我写的 Docker / K8s 系列
- 需要 CI/CD(每个服务独立构建、独立发布)
- 需要版本兼容(新老接口并存期)
- 需要 API 网关(统一入口、鉴权、限流)
- 需要 DevOps 能力(SRE 文化)
团队没有这些能力,上微服务 = 上灾难。
|
八、账单汇总:值得吗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 拆成微服务,你要新增的基础设施清单:
□ 服务注册发现 □ 配置中心
□ API 网关 □ 分布式事务/一致性
□ 链路追踪 □ 指标监控
□ 日志聚合 □ 熔断/限流/重试(Polly)
□ 容器编排(K8s) □ CI/CD 流水线
□ 幂等 + 对账 □ 版本兼容策略
收益(只有规模到了才兑现):
✓ 独立部署、独立扩容、技术栈解耦、故障隔离、团队解耦
判断标准:
规模/团队/解耦需求 带来的收益 > 上面这份税单 → 拆
否则 → 老老实实模块化单体
这就是第一篇说的"权衡"。
|
九、小结
- 分布式税:单体里免费的能力,微服务里每一项都要自建
- 网络不可靠是根源:每次跨服务调用都要处理超时/重试/幂等/降级
- 服务发现 + 配置中心:解决"找谁"和"用什么配置”
- 数据一致性是最重的税:Saga/最终一致/幂等/对账(下一篇详谈)
- 可观测性:链路追踪 + 指标 + 日志,否则微服务是黑盒
- 弹性:超时/重试/熔断/限流/降级/舱壁,防止雪崩
- 运维:K8s + CI/CD + 网关 + 版本兼容
- 决策:只有当解耦收益 > 这份税单,才值得拆
下一篇,把最重的一笔税——分布式数据一致性——彻底讲透。