单体 vs 微服务:如何权衡
单体架构(Monolith):
┌────────────────────────────────────────────┐
│ 单体应用进程 │
│ │
│ 用户模块 │ 订单模块 │ 支付模块 │ 库存模块 │
│ │ │ │ │
│ 共享内存 + 本地函数调用 │
│ │
└──────────────────────────┬─────────────────┘
│
┌────────▼───────┐
│ 单一数据库 │
└────────────────┘
微服务架构(Microservices):
Client
│
▼
API Gateway
│
├──▶ User Service ──▶ [User DB]
├──▶ Order Service ──▶ [Order DB]
├──▶ Payment Service ──▶ [Payment DB]
└──▶ Inventory Service ──▶ [Inventory DB]
每个服务独立部署、独立数据库、通过 API/MQ 通信
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 开发速度(初期) | 快 | 慢(需要搭框架) |
| 扩展粒度 | 整体扩展 | 按需独立扩展 |
| 技术栈 | 单一技术栈 | 多语言(Python+Go+Java) |
| 部署 | 一次发布全部 | 服务独立发布(灰度发布) |
| 故障影响 | 一处崩溃全局崩溃风险 | 故障隔离,局部影响 |
| 团队规模 | 适合 <20人 | 适合 >50人(康威定律) |
| 运维复杂度 | 低 | 极高(服务发现、链路追踪、分布式事务) |
⚠ 康威定律(Conway's Law)
「设计系统的组织,其所生产的设计将不可避免地反映该组织的沟通结构。」微服务架构适合大团队,因为每个团队可以端到端拥有一个服务。团队结构决定系统架构,而不是反过来。
服务发现(Service Discovery)
微服务的实例数量动态变化(弹性扩缩容),IP 地址不固定。服务发现解决「我怎么找到你」的问题。
客户端服务发现(Client-Side Discovery):
Service A ──查询──▶ Service Registry(Consul/Eureka)
│ 返回:Service B 的 IP 列表
▼
Service A ──直接调用──▶ Service B Instance(自选)
优点:Client 知道所有实例,可自定义负载均衡策略
缺点:Client 与注册中心耦合,多语言时每个语言都要实现
──────────────────────────────────────────────────────
服务端服务发现(Server-Side Discovery):
Service A ──调用──▶ Load Balancer / API Gateway
│ 查询注册中心
│ 选择实例
▼
Service B Instance
优点:Client 无需感知注册中心,简单
缺点:增加一跳(LB/Gateway),多一个组件需要维护
──────────────────────────────────────────────────────
服务注册流程:
① 服务启动 → 向 Registry 注册(IP + Port + 健康检查地址)
② Registry 定期健康检查(或服务主动心跳)
③ 服务宕机 → Registry 标记下线,从列表移除
④ 调用者从 Registry 获取最新健康实例列表
API 网关(API Gateway)
API 网关是微服务架构对外的统一入口,承担多种横切关注点(Cross-Cutting Concerns)。
API 网关职责全景:
客户端(Web / App / 第三方)
│
▼
┌───────────────────────────────────────────────┐
│ API Gateway │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 认证授权 │ │ 限流熔断 │ │ 日志监控 │ │
│ │ JWT验证 │ │ Rate Limit│ │ 链路追踪 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 协议转换 │ │ 请求聚合 │ │ 缓存响应 │ │
│ │REST→gRPC │ │ BFF模式 │ │ 减少下游 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└──────────────────┬────────────────────────────┘
│
┌────────────┬────┴───────┬────────────┐
▼ ▼ ▼ ▼
User Svc Order Svc Payment Svc Feed Svc
典型产品:
开源:Kong、Envoy、APISIX
云托管:AWS API Gateway、阿里云 API 网关
框架:Netflix Zuul、Spring Cloud Gateway
服务网格(Service Mesh)
服务网格将服务间通信的基础设施能力下沉到基础设施层,业务代码无需关心重试、熔断、链路追踪等逻辑。
Sidecar 代理模式(Istio / Linkerd):
每个服务 Pod 旁边注入一个 Sidecar(Envoy Proxy):
┌─────────────────────────────────────────────┐
│ Pod A │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ User Service │◀──▶│ Envoy Sidecar │ │
│ │ (业务代码) │ │ 自动重试、熔断 │ │
│ │ │ │ TLS加密、追踪 │ │
│ └──────────────┘ └──────┬───────────┘ │
└──────────────────────────────┼───────────────┘
│ mTLS 加密通信
┌──────────────────────────────┼───────────────┐
│ Pod B │ │
│ ┌──────────────┐ ┌───────▼──────────┐ │
│ │ Order Service│◀──▶│ Envoy Sidecar │ │
│ │ (业务代码) │ │ 流量控制、可观测 │ │
│ └──────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────┘
│
Istio Control Plane
(统一配置、策略分发)
业务代码完全不需要改动,所有功能由 Sidecar 透明处理
熔断器模式(Circuit Breaker)
熔断器防止故障在微服务链路中级联扩散。当下游服务不健康时,快速失败而不是等待超时。
熔断器三态状态机:
┌──────────────────────────────────────────┐
│ │
▼ │
┌────────┐ 失败次数超阈值 ┌──────────┐ │
│ CLOSED │─────────────────▶│ OPEN │ │
│(正常)│ │(断路中)│ │
└────────┘ └──────────┘ │
▲ │ │
│ 超时后定期 │
│ 允许一个请求 │
│ ▼ │
│ ┌────────────────┐ │
│ 请求成功 │ HALF-OPEN │ │
└───────────────────│ (半开探测中) │──────┘
└────────────────┘
│ 请求失败
└──▶ 回到 OPEN
CLOSED(关闭/正常):
请求正常通过,统计失败率
失败率 > 50%(10秒内) → 转为 OPEN
OPEN(断路/熔断):
所有请求立即失败(返回降级响应),不再调用下游
等待 30 秒后 → 转为 HALF-OPEN(探测恢复)
HALF-OPEN(半开/探测):
允许一个请求通过试探下游是否恢复
成功 → 转回 CLOSED
失败 → 继续 OPEN
实现:Netflix Hystrix(已停维)、Resilience4j、Sentinel(阿里)
链路追踪(Distributed Tracing)
一个请求跨多个服务的追踪:
Request: GET /order/123
Trace ID: abc-123-def
API Gateway User Svc Order Svc Payment Svc
│ │ │ │
t=0 │──Span 1──────▶│ │ │
t=5 │ │──Span 2──────▶│ │
t=15 │ │ │──Span 3──────▶│
t=35 │ │ │◀─────────────── │
t=40 │ │◀──────────────│ │
t=45 │◀──────────────│ │ │
Span 1:API Gateway 处理,耗时 45ms
└─ Span 2:User Svc 验证,耗时 35ms
└─ Span 3:Payment Svc 查询,耗时 20ms ← 最慢的调用!
工具:Jaeger(开源)、Zipkin、AWS X-Ray、SkyWalking(国内主流)
核心:每个请求生成 Trace ID,每个服务调用生成 Span,串联起完整调用链
▶ 面试要点
- 微服务的核心挑战:分布式事务、服务发现、链路追踪、运维复杂度。一定要说清楚你选择微服务的理由,以及这些问题如何解决。
- 熔断器 vs 重试:重试适合短暂的瞬时故障,熔断适合持续故障。对已处于 OPEN 状态的熔断器进行重试是有害的——会让雪崩更快。
- Netflix 在 AWS 上运行 700+ 个微服务,他们的经验:每个服务对应一个小团队,团队规模两个 Pizza 能喂饱(约8人)。