微服务拆分精讲 / 第 01 章:微服务导论
第 01 章:微服务导论
微服务不是银弹,但理解它何时有用、何时有害,是架构师的基本功。
1.1 什么是微服务
1.1.1 定义
微服务架构(Microservice Architecture)是一种将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,通过轻量级机制(通常是 HTTP API 或消息队列)进行通信。
这些服务围绕业务能力构建,可以通过全自动化的部署机制独立部署,并且具有最低限度的集中管理。
┌──────────────────────────────────────────────────────────────────┐
│ 微服务架构全景 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 用户服务 │ │ 订单服务 │ │ 商品服务 │ │ 支付服务 │ │
│ │ User │ │ Order │ │ Product │ │ Payment │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
│ │ 用户 DB │ │ 订单 DB │ │ 商品 DB │ │ 支付 DB │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ─ ─ ─ ─ ─ ─ ─ ─ 通信层 (HTTP/gRPC/MQ) ─ ─ ─ ─ ─ ─ ─ ─ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ API 网关 │ │ 服务注册 │ │ 配置中心 │ │ 监控告警 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└──────────────────────────────────────────────────────────────────┘
1.1.2 Martin Fowler 的核心特征
Martin Fowler 在 2014 年总结了微服务架构的一组核心特征:
| 特征 | 说明 |
|---|---|
| 组件化 via 服务 | 以服务为单位而非库(Library)进行组件化 |
| 围绕业务能力组织 | 按业务领域而非技术层拆分团队 |
| 产品而非项目 | 团队负责服务的整个生命周期(“你构建,你运行”) |
| 去中心化治理 | 每个服务可以选择最适合自身的技术栈 |
| 去中心化数据管理 | 每个服务拥有自己的数据存储 |
| 基础设施自动化 | CI/CD、容器化是微服务的基本要求 |
| 容错设计 | 设计时就考虑失败(Design for Failure) |
| 演进式设计 | 服务可以独立演进和替换 |
1.1.3 微服务 vs SOA
很多人将微服务与 SOA(面向服务架构,Service-Oriented Architecture)混淆。两者虽有相似之处,但理念差异很大:
| 维度 | SOA | 微服务 |
|---|---|---|
| 服务粒度 | 较粗,企业级服务 | 较细,单一业务能力 |
| 通信方式 | 重量级(SOAP/ESB) | 轻量级(HTTP/gRPC/消息队列) |
| 数据管理 | 共享数据库 | 每个服务独立数据库 |
| 治理方式 | 集中式治理(ESB) | 去中心化治理 |
| 部署单元 | 通常整体部署 | 独立部署 |
| 技术栈 | 统一技术栈 | 多语言/多技术栈 |
1.2 单体架构 vs 微服务
1.2.1 单体架构的典型结构
单体架构(Monolithic Architecture)将所有功能模块打包在一个部署单元中:
┌──────────────────────────────────────────────┐
│ 单体应用 (Monolith) │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 用户模块 │ │ 订单模块 │ │ 商品模块 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ └────────────┼────────────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 共享数据库 │ │
│ │ (单个 DB) │ │
│ └─────────────┘ │
│ │
│ 部署单元: 1 个 WAR/JAR/DLL │
│ 技术栈: 统一 │
│ 团队: 按技术层划分 │
└──────────────────────────────────────────────┘
1.2.2 全面对比
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 开发速度 | 初期快,后期慢 | 初期慢,中后期快 |
| 部署风险 | 整体部署,风险高 | 独立部署,风险低 |
| 技术选型 | 统一技术栈 | 多语言/多框架 |
| 可扩展性 | 整体扩展 | 按需扩展单个服务 |
| 团队协作 | 代码冲突频繁 | 团队独立开发 |
| 数据一致性 | 事务强一致 | 最终一致性 |
| 调试难度 | 本地调试简单 | 分布式调试复杂 |
| 运维成本 | 低(单个应用) | 高(大量服务) |
| 学习曲线 | 低 | 高 |
| 基础设施要求 | 低 | 高(CI/CD、监控、容器化) |
1.2.3 单体架构的困境
当项目规模增长到一定程度,单体架构会出现以下典型问题:
项目规模增长
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 构建变慢 │────▶│ 部署变慢 │────▶│ 启动变慢 │
│ (分钟级) │ │ (小时级) │ │ (分钟级) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 代码冲突 │ │ 故障蔓延 │ │ 技术债务 │
│ 频繁 │ │ 全局崩溃 │ │ 堆积 │
└─────────────┘ └─────────────┘ └─────────────┘
真实案例:某电商系统在 2019 年时单体应用包含 200 万行代码,一次全量构建需要 45 分钟,一次部署需要 2 小时(含回归测试),团队从 5 人增长到 50 人后代码冲突每天发生 20+ 次。
1.3 微服务的核心优势
1.3.1 独立部署与发布
每个微服务可以独立构建、测试和部署,互不影响:
┌───────────┐ ┌───────────┐ ┌───────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
│ v2.3.1 │ │ v1.8.0 │ │ v3.1.2 │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
▼ ▼ ▼
CI/CD CI/CD CI/CD
Pipeline Pipeline Pipeline
│ │ │
▼ ▼ ▼
部署✅ 部署✅ 部署✅
1.3.2 技术多样性
不同服务可以根据需求选择最合适的技术栈:
| 服务 | 推荐技术栈 | 原因 |
|---|---|---|
| 用户服务 | Java + Spring Boot | 成熟生态,团队熟悉 |
| 商品搜索 | Python + Elasticsearch | 数据分析能力强 |
| 实时推荐 | Go + gRPC | 高并发、低延迟 |
| 数据报表 | Node.js + React | 前后端统一 |
1.3.3 弹性伸缩
流量高峰(双十一)
┌─────────────────┐
│ 用户服务 x10 │ ← 按需扩容
│ 订单服务 x20 │ ← 大幅扩容
│ 商品服务 x5 │ ← 少量扩容
│ 支付服务 x15 │ ← 按需扩容
└─────────────────┘
│
流量低谷(凌晨)
┌─────────────────┐
│ 用户服务 x2 │ ← 缩容
│ 订单服务 x3 │ ← 缩容
│ 商品服务 x2 │ ← 缩容
│ 支付服务 x2 │ ← 缩容
└─────────────────┘
1.3.4 故障隔离
单个服务故障不会导致整个系统崩溃:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
│ ✅ 正常 │ │ ❌ 故障 │ │ ✅ 正常 │
└─────────┘ └─────────┘ └─────────┘
│ │ │
▼ ▼ ▼
正常提供 降级处理 正常提供
用户功能 "订单暂时不可用" 商品浏览
1.4 微服务的代价
微服务带来的复杂性不应该被低估。它将代码的复杂性转移到了运维的复杂性。
1.4.1 分布式系统的固有复杂性
| 复杂性 | 说明 |
|---|---|
| 网络不可靠 | 服务间调用可能超时、失败 |
| 数据一致性 | 跨服务事务处理困难 |
| 调试困难 | 请求链路跨越多个服务 |
| 运维开销 | 需要管理大量服务实例 |
| 测试复杂 | 集成测试和端到端测试难度增加 |
1.4.2 需要的基础设施
┌─────────────────────────────────────────────────────┐
│ 微服务基础设施全景 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ CI/CD │ │ 容器编排 │ │ 服务注册 │ │
│ │ Pipeline │ │ (K8s) │ │ 与发现 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ API 网关 │ │ 配置中心 │ │ 日志聚合 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 链路追踪 │ │ 监控告警 │ │ 消息队列 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 服务网格 │ │ 安全框架 │ │ 自动化测试│ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────┘
1.5 何时拆分微服务
1.5.1 适合拆分的信号
| 信号 | 描述 | 严重程度 |
|---|---|---|
| 🟡 构建时间超过 15 分钟 | 代码量大,编译/打包缓慢 | 中 |
| 🟡 部署频率受限 | 无法独立部署某个功能 | 中 |
| 🔴 团队规模超过 10 人 | 代码冲突频繁,沟通成本高 | 高 |
| 🔴 系统可用性要求极高 | 需要故障隔离和独立扩容 | 高 |
| 🔴 不同模块有不同的扩展需求 | 订单量暴增但用户量稳定 | 高 |
| 🟡 技术栈需要多样化 | 某些功能用其他语言更合适 | 中 |
| 🟢 业务边界清晰 | 模块之间有明确的业务分界 | 低(有利条件) |
1.5.2 不适合拆分的场景
| 场景 | 原因 |
|---|---|
| 初创项目/POC 阶段 | 业务未稳定,过早拆分会增加不必要的复杂性 |
| 团队规模小(< 5 人) | 运维成本高于收益 |
| 没有 DevOps 文化 | 缺乏自动化运维基础 |
| 业务边界模糊 | 拆分后会产生大量跨服务调用 |
| 性能要求极高且调用链长 | 网络延迟可能成为瓶颈 |
1.5.3 决策矩阵
团队规模
小 (<5人) │ 大 (>10人)
───────────┼────────────
业务复杂度 低 │ 单体 │ 模块化单体
───────────┼────────────
高 │ 模块化单体│ 微服务 ✅
💡 建议:优先考虑模块化单体(Modular Monolith)作为过渡方案。先在单体内按业务模块做好边界划分,再逐步拆分为独立服务。
1.6 业务场景:电商平台的架构演进
第一阶段:单体(0-10 万用户)
┌────────────────────────────────┐
│ 电商单体应用 (Spring Boot) │
│ │
│ 用户 + 商品 + 订单 + 支付 │
│ ↓ │
│ MySQL (单库) │
└────────────────────────────────┘
- 1 个代码仓库,1 个部署单元
- 5 人开发团队
- 每周发布 1 次
第二阶段:模块化单体(10-100 万用户)
┌────────────────────────────────────────┐
│ 电商单体 (模块化) │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │用户域│ │商品域│ │订单域│ │支付域│ │
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │
│ └────────┼────────┼────────┘ │
│ ▼ │
│ MySQL (逻辑分库) │
└────────────────────────────────────────┘
- 1 个代码仓库,按 Maven Module 划分
- 15 人团队,按业务域分组
- 每周发布 2-3 次
第三阶段:微服务(100 万+ 用户)
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│用户 │ │商品 │ │订单 │ │支付 │
│服务 │ │服务 │ │服务 │ │服务 │
└──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
│ │ │ │
┌──┴───┐ ┌──┴───┐ ┌──┴───┐ ┌──┴───┐
│MySQL │ │MySQL │ │MySQL │ │MySQL │
│+Redis│ │+ES │ │+Redis│ │+MySQL│
└──────┘ └──────┘ └──────┘ └──────┘
- 4 个代码仓库,独立部署
- 30+ 人团队,每个服务 5-8 人
- 每天多次发布
1.7 微服务架构的关键模式
在后续章节中会详细讲解以下模式,这里先做一个总览:
| 模式 | 说明 | 对应章节 |
|---|---|---|
| API Gateway | 统一入口,路由/限流/认证 | 第 06 章 |
| Service Discovery | 服务自动注册与发现 | 第 07 章 |
| Circuit Breaker | 熔断器,防止级联故障 | 第 17 章 |
| Saga | 分布式事务编排 | 第 10 章 |
| CQRS | 读写分离架构 | 第 05 章 |
| Event Sourcing | 事件溯源 | 第 08 章 |
| Strangler Fig | 绞杀者模式,渐进迁移 | 第 16 章 |
| Sidecar | 边车模式,服务网格基础 | 第 09 章 |
1.8 常见误区
| 误区 | 事实 |
|---|---|
| “微服务能解决所有问题” | 微服务只是架构选择之一,有明确的适用场景 |
| “服务越小越好” | 过度拆分导致分布式单体,比单体更糟 |
| “先拆了再说” | 没有清晰的业务边界,拆分只会增加混乱 |
| “微服务不需要设计” | 微服务对架构设计要求更高 |
| “用了 Docker 就是微服务” | 容器化是手段,不是目的 |
| “每个服务用不同语言” | 技术多样性是优势但不是必须,过度追求反而增加维护成本 |
⚠️ 注意事项
- 不要为了微服务而微服务——先评估是否真的需要
- 基础设施先行——没有 CI/CD、监控、日志聚合,不要开始拆分
- 团队准备度——确保团队具备分布式系统开发能力
- 渐进式演进——大爆炸式重写(Big Bang Rewrite)几乎一定会失败
- 数据先行——数据库的拆分是最难的部分,优先规划数据架构
📖 扩展阅读
- Martin Fowler - Microservices (martinfowler.com/articles/microservices.html) — 微服务架构的经典定义
- Sam Newman - Building Microservices (O’Reilly) — 微服务实践的权威指南
- Chris Richardson - Microservices Patterns (Manning) — 微服务设计模式大全
- Martin Fowler - MonolithFirst — 先从单体开始,演进到微服务
- ThoughtWorks Technology Radar — 跟踪微服务技术趋势
本章小结
| 要点 | 说明 |
|---|---|
| 微服务本质 | 小型、独立、围绕业务能力的服务 |
| 适用场景 | 大团队、高可用、业务边界清晰 |
| 不适用场景 | 小团队、初创项目、业务不稳定 |
| 核心权衡 | 用运维复杂性换取开发和部署的灵活性 |
| 推荐路径 | 单体 → 模块化单体 → 微服务 |
📌 下一章:第 02 章:拆分原则 — 学习微服务拆分的核心原则与康威定律。