微服务架构概述
架构演进历程
软件架构的发展经历了三个阶段,每一次演进都为了解决前一阶段的核心痛点。
单体架构(Monolithic Architecture)
早期应用多采用单体架构,所有功能模块(用户管理、订单、支付、库存等)被打包在同一个部署单元中。
┌──────────────────────────┐
│ 单体应用 WAR/JAR │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │用户 │ │订单 │ │支付 │ │
│ │模块 │ │模块 │ │模块 │ │
│ └─────┘ └─────┘ └─────┘ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │库存 │ │商品 │ │通知 │ │
│ │模块 │ │模块 │ │模块 │ │
│ └─────┘ └─────┘ └─────┘ │
│ ┌──────────┐ │
│ │ 共享数据库 │ │
│ └──────────┘ │
└──────────────────────────┘优点:开发简单、部署便捷、测试容易、调用延迟低。 痛点:代码耦合严重、扩展粒度粗、团队协作困难、技术栈锁定。
面向服务架构(SOA)
SOA 通过企业服务总线(ESB)实现服务间的集成与通信。
服务提供者 A ────┐
├──→ [ESB 企业服务总线] ──→ 服务消费者
服务提供者 B ────┘ (协议转换/路由/编排)优点:服务可重用、异构系统集成。 痛点:ESB 成为单点瓶颈、治理过重、通信开销大。
微服务架构(Microservices)
微服务将 SOA 去中心化,每个服务独立部署、独立扩展、独立演进。
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 用户服务 │ │ 订单服务 │ │ 支付服务 │
│ (独立进程) │ │ (独立进程) │ │ (独立进程) │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└──────────────┼──────────────┘
┌────┴────┐
│ API 网关 │
└─────────┘架构对比
| 维度 | 单体架构 | 分布式架构(SOA) | 微服务架构 |
|---|---|---|---|
| 部署粒度 | 单一部署单元 | 按业务领域拆分,通过 ESB 集成 | 每个服务独立部署 |
| 扩展方式 | 垂直扩展(增加机器) | 粗粒度水平扩展 | 细粒度独立扩展 |
| 通信机制 | 进程内方法调用 | ESB / SOAP / WebService | HTTP/REST / gRPC / 消息队列 |
| 数据管理 | 共享数据库 | 共享数据库或分库 | 每个服务独享数据库(Database per Service) |
| 技术栈 | 单一技术栈 | 异构但受 ESB 约束 | 完全异构,语言/框架不限 |
| 团队结构 | 职能团队(前端/后端/测试) | 按层分工 | 按业务组织(跨职能小团队) |
| 测试复杂度 | 低 | 中 | 高(需契约测试、集成测试) |
| 故障隔离 | 差(一个模块崩溃 → 整个应用宕机) | 中 | 好(故障仅限于单个服务) |
| 运维成本 | 低 | 中 | 高(需容器编排、服务发现、监控等) |
| 交付频率 | 低(周/月级) | 中 | 高(日/小时级) |
| 适用场景 | 小型团队、简单业务、MVP 阶段 | 企业级系统集成 | 大型复杂业务、快速迭代需求 |
核心特征
微服务并非简单的"拆小即好",而是遵循一系列设计原则:
自治性(Autonomy)
每个服务可以独立开发、测试、部署和扩展,不依赖其他服务的协调。
服务 A ──→ 独立数据库 ──→ 独立 CI/CD ──→ 独立部署 ──→ 独立扩展
服务 B ──→ 独立数据库 ──→ 独立 CI/CD ──→ 独立部署 ──→ 独立扩展去中心化(Decentralization)
- 去中心化数据管理:每个服务拥有自己的数据库,避免共享 schema
- 去中心化治理:团队可自主选择技术栈(Polyglot)
- 去中心化通信:避免中央总线,服务间直接通信或通过轻量级消息代理
容错设计(Resilience)
默认假设外部服务可能不可用,通过熔断、降级、重试、隔离等模式保障系统整体可用性。
服务 A ──→ 调用服务 B
│
├── 成功 → 正常返回
├── 超时 → 熔断器打开 → 快速失败
└── 失败 → 降级 → 返回兜底数据基础设施自动化(Infrastructure Automation)
微服务架构严重依赖自动化基础设施:
| 领域 | 工具/技术 |
|---|---|
| 容器化 | Docker、Containerd |
| 编排调度 | Kubernetes、Nomad |
| 服务发现 | Nacos、Consul、Eureka |
| 配置中心 | Apollo、Nacos Config、Consul KV |
| CI/CD | Jenkins、GitLab CI、GitHub Actions |
| 可观测性 | Prometheus + Grafana、ELK、Jaeger |
业务能力优先(Business Capability)
服务边界围绕业务能力而非技术层次划分,遵循 "Conway's Law"——系统架构反映组织沟通结构。
优缺点分析
优点
| 优势 | 说明 |
|---|---|
| 独立部署 | 修改一个服务不影响其他服务,降低发布风险 |
| 技术多样性 | 不同服务可使用不同技术栈,选择最适合的语言和框架 |
| 弹性扩展 | 仅对瓶颈服务进行水平扩展,资源利用率高 |
| 故障隔离 | 单个服务崩溃不会导致整个系统不可用 |
| 团队自治 | 小团队拥有完整的服务所有权,提高交付效率 |
| 可维护性 | 代码库小、职责单一,易于理解和维护 |
缺点
| 劣势 | 说明 |
|---|---|
| 分布式复杂性 | 网络延迟、数据一致性、分布式事务等问题 |
| 运维成本高 | 需要容器编排、服务网格、监控告警等基础设施 |
| 调试困难 | 跨服务调用链路长,问题定位和排查难度大 |
| 数据一致性 | 最终一致性模型使业务逻辑更复杂 |
| 服务间耦合 | 服务间 API 契约变更需多方协调 |
| 重复代码 | 公共功能(鉴权、日志等)在每个服务中重复实现 |
设计原则
单一职责原则(Single Responsibility Principle)
每个服务只负责一个明确的业务领域,有清晰的边界。
✅ 正确示例:
┌─ 订单服务:只处理订单生命周期
└─ 库存服务:只管理库存增减
❌ 错误示例:
┌─ 订单服务:包含订单、库存查询、用户信息
└─ ……领域驱动设计(Domain-Driven Design, DDD)
通过**限界上下文(Bounded Context)划分服务边界,用通用语言(Ubiquitous Language)**统一团队沟通。
┌──────────────────────────────────────────┐
│ 电商系统 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐│
│ │ 订单上下文 │ │ 库存上下文 │ │ 支付上下文 ││
│ │ (Order) │ │(Inventory)│ │(Payment) ││
│ └──────────┘ └──────────┘ └──────────┘│
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 用户上下文 │ │ 商品上下文 │ │
│ │ (User) │ │ (Product)│ │
│ └──────────┘ └──────────┘ │
└──────────────────────────────────────────┘DDD 战术模式:
| 模式 | 说明 |
|---|---|
| 实体(Entity) | 有唯一标识的可变对象 |
| 值对象(Value Object) | 不可变,由属性值定义 |
| 聚合(Aggregate) | 一组相关对象的集合,通过聚合根访问 |
| 领域事件(Domain Event) | 记录领域中发生的事情 |
| 仓储(Repository) | 提供聚合的持久化与检索 |
| 领域服务(Domain Service) | 处理不属于单个实体或值对象的业务逻辑 |
CQRS(命令查询职责分离)
将读操作和写操作分离到不同的模型中,优化各自的性能和扩展方式。
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ 客户端/API网关 │ │ Command │ │ Query │
│ │───→│ 写模型 │ │ 读模型 │
│ │ │ (写优化) │ │ (读优化) │
└─────────────┘ └──────┬───────┘ └──────┬───────┘
│ │
│ ┌──────────┐ │
└───→│ 事件总线/ │←───┘
│ 消息队列 │
│ (同步/异步)│
└──────────┘// Command(写)
public class CreateOrderCommand {
private String userId;
private List<OrderItem> items;
private Address shippingAddress;
}
// Query(读)
public class OrderSummaryQuery {
private String userId;
private PageRequest page;
}
// 写模型
@Service
public class OrderCommandService {
public void handle(CreateOrderCommand cmd) { /* 事务性写入 */ }
}
// 读模型
@Service
public class OrderQueryService {
public OrderSummaryDTO handle(OrderSummaryQuery query) { /* 优化查询 */ }
}事件驱动(Event-Driven)
服务间通过异步事件进行通信,实现松耦合。
┌──────────┐ 发布事件 ┌──────────┐
│ 订单服务 │───→ OrderCreated ───→│ 库存服务 │
└──────────┘ 事件总线 └──────────┘
│
扣减库存
│
发送事件
↓
┌──────────┐
│ 通知服务 │
└──────────┘事件类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| 领域事件 | 业务领域中发生的事实 | OrderCreated、PaymentSucceeded |
| 集成事件 | 服务间协调的事件 | InventoryReserved、ShipmentDelayed |
| Saga 事件 | 分布式事务的补偿事件 | OrderCompensated、PaymentRefunded |
实施挑战
分布式事务
跨服务的数据一致性是最大挑战之一,传统 ACID 事务不再适用。
解决方案:
Saga 模式
├── 编排(Choreography):各服务通过事件驱动协作
│ └── 订单服务 → OrderCreated → 库存服务 → 支付服务 → …
│
└── 协调(Orchestration):由协调器统一控制
└── Saga 协调器 → 调用订单服务 → 调用库存服务 → 调用支付服务
← 失败 → 调用补偿事务
TCC(Try-Confirm-Cancel)
└── Try: 预留资源(冻结库存)
Confirm:确认执行业务(扣减库存)
Cancel: 取消预留(解冻库存)| 方案 | 一致性 | 复杂性 | 性能 | 适用场景 |
|---|---|---|---|---|
| Saga | 最终一致 | 中 | 高 | 长活事务 |
| TCC | 最终一致 | 高 | 中 | 短事务、高一致性 |
| 可靠消息 | 最终一致 | 低 | 高 | 允许延迟一致的场景 |
服务治理
服务数量增多后,服务注册发现、负载均衡、流量控制等成为基础需求。
服务治理框架:
┌─────────────────────┐
│ API 网关 │ ── 统一入口、限流、鉴权
├─────────────────────┤
│ 服务网格 │ ── Sidecar 代理(Istio/Linkerd)
├─────────────────────┤
│ 服务注册中心 │ ── Nacos / Consul / Zookeeper
├─────────────────────┤
│ 配置中心 │ ── Apollo / Nacos Config
├─────────────────────┤
│ 流量管控 │ ── 熔断(Hystrix/Sentinel)、限流、灰度
└─────────────────────┘可观测性
分布式系统需要三大支柱支撑运维:
| 支柱 | 目标 | 工具 |
|---|---|---|
| 日志(Logging) | 记录离散事件 | ELK(Elasticsearch + Logstash + Kibana)、Loki |
| 指标(Metrics) | 聚合可计数数据 | Prometheus + Grafana |
| 链路追踪(Tracing) | 追踪请求在服务间的完整路径 | Jaeger、Zipkin、SkyWalking |
请求链路示例:
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ Gateway │──→│ 订单服务 │──→│ 库存服务 │──→│ 支付服务 │
└────────┘ └────────┘ └────────┘ └────────┘
Trace ID: a1b2c3d4
Span 1: Gateway.span (0ms → 1050ms)
Span 2: OrderService.span (10ms → 1040ms)
Span 3: InventoryService.span (50ms → 200ms)
Span 4: PaymentService.span (250ms → 1000ms)CI/CD 与 DevOps
微服务数量增长后,手动部署不再可行,必须建立自动化的构建与交付流水线。
CI/CD 流水线:
代码提交 → 单元测试 → 构建镜像 → 集成测试 → 制品仓库 → 预发部署 → 验收测试 → 生产发布
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Git JUnit Docker Contract Harbor/ K8s Staging E2E K8s Prod
/Maven Build Test AWS ECR关键实践:
- 基础设施即代码(IaC)——使用 Terraform / Pulumi 管理基础设施
- 不可变基础设施——每次部署使用新镜像,不修改运行中的容器
- 蓝绿部署 / 金丝雀发布——降低发布风险
- 灰度发布 + 流量染色——小范围验证新版本
总结
微服务架构是一把双刃剑。它为解决大型复杂系统的快速迭代、独立部署和弹性扩展提供了有效手段,但同时也引入了分布式系统的固有复杂性。是否采用微服务,取决于业务复杂度、团队规模和交付节奏——对于多数中小型系统,一个组织良好的单体架构或许是更务实的选择。