引言
微服务架构不是银弹。它解决了单体架构的一些问题,但也带来了分布式系统特有的复杂性。本文梳理了微服务领域最核心的几种设计模式,帮助你理解它们解决的问题和适用场景。更重要的是,我们会讨论"什么时候不应该用微服务"——这个问题的答案往往比"怎么用微服务"更有价值。
一、API Gateway(API 网关)
在微服务架构中,客户端直接调用多个服务会带来很多问题:需要知道所有服务的地址、需要处理多种认证方式、需要多次网络请求。API Gateway 作为系统的统一入口,负责路由、认证、限流、聚合等功能。
# 架构示意
Client (Browser / Mobile App)
|
[API Gateway] -- 认证、限流、日志、路由
|
+----+----+----+
| | | |
[用户] [订单] [商品] [支付]
服务 服务 服务 服务
常见的 API Gateway 实现包括 Kong、Nginx + Lua、Spring Cloud Gateway、以及云服务商的原生网关(AWS API Gateway、阿里云 API Gateway)。
二、Service Discovery(服务发现)
在微服务环境中,服务实例的地址会动态变化(扩缩容、故障转移、滚动更新)。服务发现模式解决了"服务 A 如何找到服务 B"的问题。
# 服务发现架构
[服务 A] -- 2. 查询服务 B 的地址 --> [服务注册中心]
|
[服务 B-1] -- 1. 注册 --> [服务注册中心] | Consul / Etcd / Nacos
[服务 B-2] -- 1. 注册 --> |
[服务 B-3] -- 1. 注册 -->
客户端发现(Client-side Discovery):服务消费者从注册中心获取地址列表,自己做负载均衡。服务端发现(Server-side Discovery):通过负载均衡器(如 AWS ELB)转发请求。
三、Circuit Breaker(熔断器)
当某个服务不可用时,持续的重试请求会让问题雪崩。熔断器模式通过监控失败率,在达到阈值时"断开电路",快速失败而不是继续重试。
# 熔断器状态机
[CLOSED] -- 失败率达到阈值 --> [OPEN]
^ |
| v
[HALF-OPEN] <-- 超时后尝试部分请求 --
常见的熔断器实现:Netflix Hystrix(已停止维护)、Resilience4j、Sentinel(阿里开源)、Istio 的熔断功能。
四、Saga 模式:分布式事务
在微服务中,跨服务的数据库事务不能用传统的 ACID 事务。Saga 模式将一个大事务拆分为多个本地事务,每个本地事务有对应的补偿操作。
# 订单 Saga 流程
订单服务:创建订单(状态:待支付)
|
支付服务:扣款
|-- 失败 --> 补偿:订单服务取消订单
|
库存服务:扣减库存
|-- 失败 --> 补偿:支付服务退款 + 订单服务取消订单
|
物流服务:创建物流单
|-- 失败 --> 补偿:库存服务恢复库存 + 支付服务退款 + 订单服务取消订单
Saga 有两种实现方式:编排(Orchestration,由一个 Saga 管理器协调)和协同(Choreography,各服务通过事件驱动)。
五、Event Sourcing 与 CQRS
Event Sourcing(事件溯源):不存储当前状态,而是存储所有状态变更事件。当前状态通过重放事件计算得出。
CQRS(命令查询职责分离):将读操作和写操作分离到不同的模型中。写操作使用规范化的事件存储,读操作使用针对查询优化的非规范化视图。
# CQRS 架构示意
[Command API] --> [Event Store] --> [Event Bus]
| |
写操作(增删改) [Projections]
|
[Query API]
|
读操作(查询)
六、Strangler Fig 模式
将单体应用逐步迁移到微服务,而不是一次性重写。新功能在微服务中实现,旧功能逐步从单体中"绞杀"(strangle)。
# 迁移策略
1. 在单体前放置路由层
2. 新功能直接在微服务中实现
3. 旧功能逐步迁移:路由层将请求从单体重定向到新服务
4. 单体应用最终被完全"绞杀"
七、Sidecar 模式
将辅助功能(日志、监控、网络代理)从业务服务中分离出来,部署在同一个 Pod 或容器组中。Service Mesh(如 Istio)就是 Sidecar 模式的典型应用。
# Kubernetes Pod 中的 Sidecar
+---------------------------+
| Pod |
| +----------+ +----------+|
| | 业务容器 | | Sidecar ||
| | (应用) | | (Envoy) ||
| +----------+ +----------+|
| | | |
| localhost <--> 网络代理 |
+---------------------------+
八、什么时候不应该用微服务
- 团队规模小(< 10 人):微服务的管理成本远大于收益
- 产品早期阶段:需求快速变化时,微服务边界难以确定
- 没有 DevOps 基础设施:自动化部署、监控、日志聚合是微服务的前提
- 业务逻辑简单:CRUD 应用不需要微服务
- 没有分布式系统经验:分布式事务、最终一致性、网络延迟都是巨大的挑战
总结
微服务不是架构的目标,而是解决特定问题的手段。选择微服务前,先问自己:单体架构真的无法满足需求了吗? 如果答案是肯定的,再逐步引入本文介绍的模式。记住 Martin Fowler 的建议:从单体开始,在确有需要时再拆分,而不是反过来。