第 4 章 · 微服务拆分与领域边界
本章讲解 何时拆、怎么拆 微服务:bounded context、数据归属、API 契约、服务治理与贤紫 K8s 落地。
前置:PaaS 全栈联调;架构第 1~3 章;L3 场景常考微服务设计。
4.1 单体 vs 微服务
| 维度 | 模块化单体 | 微服务 |
|---|
| 上手速度 | 快(单仓单部署) | 慢(多仓多流水线) |
| 部署 | 一次全发,回滚简单 | 独立发布,版本矩阵复杂 |
| 故障隔离 | 一进程挂全挂 | 可隔离(若异步边界清晰) |
| 数据事务 | 本地 ACID | 分布式事务 / Saga |
| 团队扩展 | 8 人内尚可 | 按上下文分团队 |
| 运维成本 | 低 | 高(注册发现、链路、配置) |
决策公式(参考):
若 (团队数 × 发布频率冲突) + (模块资源需求差异) > 运维成熟度得分
→ 考虑拆分
否则 → 模块化单体 + 清晰包边界
| 运维成熟度 | 得分项 |
|---|
| 有 CI/CD、监控、日志、链路 | +2 |
| 有 K8s + 配置中心 | +2 |
| 无自动测试、无回滚 | -3 |
4.2 领域驱动拆分(DDD 轻量)
电商领域(Domain)
├── 商品上下文(Catalog) — SKU、类目、价格展示
├── 订单上下文(Order) — 下单、状态机、履约
├── 库存上下文(Inventory) — 可售库存、预占、释放
├── 支付上下文(Payment) — 支付单、渠道、对账
├── 用户上下文(User) — 账号、地址、会员等级
└── 营销上下文(Promotion) — 券、满减、活动规则
| 原则 | 说明 | 验收 |
|---|
| 高内聚 | 同一上下文内因同一业务规则变化 | 改促销不动订单表结构 |
| 低耦合 | 上下文间仅 API / 领域事件 | 无跨库 JOIN |
| 数据归属 | 每个服务拥有自己的库表 | 一服务一 Schema 起 |
| 通用语言 | 文档与代码同名同义 | 「订单」不混叫「单据」 |
4.2.1 贤紫商城上下文映射(示例)
| 上下文 | 部署名 | Namespace | 数据库 |
|---|
| 商品 | catalog-api | app | catalog_db |
| 订单 | order-api | app | order_db |
| 库存 | inventory-api | app | inventory_db |
| BFF | customer-web | app | 无(聚合调用) |
禁止:order-api 与 inventory-api 直连同一张 stock 表。
4.3 拆分时机信号
| 信号 | 量化参考 | 建议动作 |
|---|
| 发布拖累 | 单次发布 > 2h;失败率 > 10% | 独立 Deployment |
| 团队冲突 | > 8 人同仓;PR 等待 > 1 天 | 按上下文分仓 |
| 资源差异 | 某 API CPU 8 核,其余 0.5 核 | 拆出高耗服务 |
| 扩缩不一 | 搜索 QPS 10× 于后台 | 独立 HPA |
| 技术异构 | 网关 Go + 核心 Java | 允许,但控制数量 |
| 合规隔离 | 支付需 PCI 隔离 | 独立网络域 |
行业案例 · 某 B2B 平台:5 团队共用一个 Django 单体,每周五「发布夜」平均 rollback 2 次。按 订单 / 合同 / 结算 三上下文拆服务后,单服务发布 < 15min,全站 rollback 频率降 70%。
4.4 API 契约与版本
4.4.1 REST 约定
GET /api/v1/orders/{id}
POST /api/v1/orders
PATCH /api/v1/orders/{id}/status
| 实践 | 说明 | 反模式 |
|---|
| URL 版本 | /v1/ 明确 | 无版本直接改字段 |
| 向后兼容 | 加字段 OK;删改走 v2 | 强制全客户端同发 |
| 错误码统一 | {code, message, traceId} | 各服务 HTTP 体格式不一 |
| 分页标准 | page/size 或 cursor | 每服务不同参数名 |
| 文档 | OpenAPI 3 入库 CI | 口头约定 |
# openapi-order-v1.yaml 片段
paths:
/api/v1/orders:
post:
operationId: createOrder
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Created
headers:
X-Request-Id:
schema: { type: string }
4.4.2 同步 vs 异步集成
| 方式 | 适用 | 延迟 | 耦合 |
|---|
| REST 同步 | 查询、强依赖下一步结果 | 低 | 中 |
| gRPC | 内部高性能调用 | 低 | 中 |
| 消息事件 | 副作用、通知、统计 | 中 | 低 |
| 批量对账 | 日终结算 | 高 | 低 |
4.5 K8s 服务发现与调用
Pod (order-api) ──► http://inventory-api.app.svc.cluster.local:8080/api/v1/stock/reserve
| 要素 | 说明 |
|---|
| DNS | <service>.<namespace>.svc.cluster.local |
| 端口 | Service port 非容器 targetPort 混用 |
| 超时 | 客户端 connect + read 超时必设 |
| 重试 | 仅幂等 GET;写操作慎重重试 |
apiVersion: v1
kind: Service
metadata:
name: order-api
namespace: app
spec:
selector:
app: order-api
ports:
- name: http
port: 80
targetPort: 8080
# 客户端配置示例
INVENTORY_BASE = os.getenv(
"INVENTORY_URL",
"http://inventory-api.app.svc.cluster.local:80",
)
TIMEOUT = (2.0, 5.0) # connect, read