关于 microservices-decomposition
为系统拆分或新系统设计生成微服务分解方案,面向架构师与开发团队,依据 DDD 界定限界上下文和服务边界。方案还覆盖通信、数据归属、迁移步骤及团队所有权。
主要功能
- 01分析领域与限界上下文
- 02设计服务边界和职责
- 03选择同步或异步通信模式
- 04定义数据所有权和迁移方式
- 05规划分阶段迁移与团队归属
适用场景
- 01规划单体系统的渐进式拆分
- 02为新系统设计服务边界
- 03协调服务依赖、数据归属与团队职责
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mohitagw15856/ pm-claude-skills --skill microservices-decomposition安装后在 Claude Code 中输入/microservices-decomposition确认已加载。
详细介绍
微服务拆分
为一个系统设计完整的微服务拆分方案——无论是拆分现有单体,还是为新系统设计服务边界。方案应以领域驱动设计(DDD)概念为基础:先识别限界上下文,再据此划分服务边界。明确通信模式的选择(同步还是异步、事件还是 RPC)、数据所有权规则,以及拆分单体时务实可行的迁移计划。康威定律确实存在——请加入组织对齐章节。交付内容应具体到团队可以据此开始实施,而不只是抽象的架构图。
所需输入
如果尚未提供,请询问以下信息:
- 系统或领域描述——系统的用途、核心领域,以及所支持的关键业务流程
- 当前架构——单体(描述技术栈和大致模块结构)、部分服务化(列出现有服务),或从零构建
- 团队结构——团队数量、已知的团队名称,以及大致的团队规模;这些信息决定服务归属
- 性能和可扩展性要求——各领域是否有具体的 SLA、负载特征或扩展限制
- 迁移约束——哪些部分无法一次性重写、严格期限、零停机要求、预算限制
- 集成点——无法更改的外部系统、第三方 API 或遗留系统
如果是拆分单体,还要询问:代码库的大致规模、目前最难修改的部分,以及团队在哪些地方最常遇到耦合带来的阻碍。
输出格式
微服务拆分:[系统名称]
作者: [姓名 / 团队] 日期: [日期] 架构类型: [单体拆分 / 新系统设计] 当前状态: [用一句话描述当前情况] 目标状态: [用一句话描述期望的最终状态]
1. 领域分析
核心领域
[用一段话说明:该系统的核心领域是什么?业务的本质是什么?其竞争优势来自哪里?核心领域应获得最多投入,并拥有最清晰的服务边界。]
领域映射
在划分服务边界之前,先列出所有重要子域。对每个子域进行分类:
| 子域 | 类型 | 描述 | 在单体中的当前位置 |
|---|---|---|---|
| [子域,例如订单管理] | 核心 | [它的功能及重要性] | [模块 / 包名称或“新建”] |
| [子域,例如库存] | 核心 | [描述] | [位置] |
| [子域,例如通知] | 支撑 | [描述] | [位置] |
| [子域,例如计费] | 支撑 | [描述] | [位置] |
| [子域,例如报表] | 通用 | [描述——可考虑采用现成解决方案] | [位置] |
| [子域,例如用户身份验证] | 通用 | [描述] | [位置] |
子域类型: 核心 = 形成竞争优势,需精心构建;支撑 = 必不可少但不形成差异化,务实构建;通用 = 商品化能力,可采购或使用开源方案。
2. 限界上下文图(ASCII)
┌─────────────────────────────────────────────────────────────────┐
│ [System Name] │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ [Context A] │ │ [Context B] │ │
│ │ │─ ─►│ │ │
│ │ [key concepts] │ │ [key concepts] │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │ │
│ │ event │ sync │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ [Context C] │ │ [Context D] │ │
│ │ │ │ │ │
│ │ [key concepts] │ │ [key concepts] │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ┌────────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ [Context E] │ │
│ │ [key concepts] │ │
│ └──────────────────┘ │
│ │
│ External: [Third-party system] ──► [Context that owns it] │
└─────────────────────────────────────────────────────────────────┘
Legend: ──► sync call - -► async event ═══ shared kernel
使用领域分析得出的实际限界上下文绘制此图。将经常通信的上下文放得更近,并在箭头上标注关系类型。
上下文关系
| 上游上下文 | 下游上下文 | 关系类型 | 集成模式 |
|---|---|---|---|
| [上下文 A] | [上下文 B] | 客户端—供应商 | REST API 调用 |
| [上下文 B] | [上下文 C] | 已发布语言 | 通过消息总线传递领域事件 |
| [上下文 X] | [上下文 Y] | 遵从者 | [下游遵循上游的模型] |
| [上下文 X] | [上下文 Y] | 防腐层 | [防腐层将上游模型转换为本地模型] |
3. 拟议服务清单
| 服务名称 | 限界上下文 | 核心职责 | 负责团队 | 技术栈 | 优先级 |
|---|---|---|---|---|---|
| [service-name] | [Context] | [一句话说明此服务拥有并负责的内容] | [Team] | [Language/framework] | [P1/P2/P3] |
| [service-name] | [Context] | [Responsibility] | [Team] | [Stack] | [Priority] |
| [service-name] | [Context] | [Responsibility] | [Team] | [Stack] | [Priority] |
| [service-name] | [Context] | [Responsibility] | [Team] | [Stack] | [Priority] |
| [service-name] | [Context] | [Responsibility] | [Team] | [Stack] | [Priority] |
服务数量:[N 个拟议服务],对应 [M 个限界上下文]。[说明是否有上下文映射到多个服务,以及原因——例如:“订单上下文拆分为订单接入和订单履约服务,因为它们的可扩展性需求不同。”]
服务职责规则(适用于上述每项服务)
- 仅拥有一个限界上下文——服务不得跨越两个限界上下文
- 拥有自己的数据——其他服务不得直接访问其数据库
- 可独立部署——无需与其他服务协调部署
- 有明确的负责团队——单个服务不得由多个团队共同负责
- 提供明确的 API 契约——而非内部实现
4. 服务间通信模式
模式决策矩阵
| 通信需求 | 推荐模式 | 理由 |
|---|---|---|
| 查询其他服务的当前状态 | 同步 REST / gRPC | 需要低延迟;调用方需要立即获得响应 |
| 通知其他服务状态变更 | 异步领域事件 | 解耦服务;支持多个消费者;发送方不关心事件何时处理 |
| 跨服务的长时间运行工作流 | 异步 Saga(编排或协调) | 没有单个服务拥有完整工作流;步骤失败时需要回滚 |
| 读密集型跨服务聚合 | CQRS 读模型 / 物化视图 | 避免读取时频繁进行同步调用;构建适用场景的读模型 |
| 向客户端实时推送 | WebSocket 网关服务 | 集中管理连接;服务发出事件,由网关推送 |
各服务的通信决策
| 服务 | 调用(同步) | 发布(事件) | 订阅(事件) |
|---|---|---|---|
| [service-name] | [service-name (endpoint)] | [EventName] | [EventName] |
| [service-name] | — | [EventName], [EventName] | [EventName] |
| [service-name] | [service-name (endpoint)] | — | [EventName] |
事件目录
| 事件名称 | 生产者 | 消费者 | 负载(关键字段) | 触发条件 |
|---|---|---|---|---|
| [OrderPlaced] | [order-service] | [inventory-service, notification-service] | orderId, customerId, lineItems, totalAmount | 客户提交订单 |
| [InventoryReserved] | [inventory-service] | [order-service] | orderId, reservationId, items | 库存预留成功 |
| [PaymentProcessed] | [payment-service] | [order-service, notification-service] | orderId, paymentId, amount, status | 付款已确认 |
5. 数据所有权矩阵
每条数据都恰好由一个服务负责。其他服务可以缓存数据或构建读模型,但不会写入所有者的数据库。
| 数据实体 | 所属服务 | 权威存储 | 使用方 | 访问模式 |
|---|---|---|---|---|
| [Order] | [order-service] | [PostgreSQL] | [fulfillment-service, reporting-service] | 事件订阅 + 读取 API |
| [Customer] | [customer-service] | [PostgreSQL] | [order-service, notification-service] | 同步 API 调用 |
| [Product Catalog] | [catalog-service] | [PostgreSQL] | [order-service, inventory-service] | 同步 API + 本地缓存副本 |
| [Inventory Level] | [inventory-service] | [Redis + PostgreSQL] | [catalog-service (只读)] | 事件订阅 |
| [Payment Record] | [payment-service] | [PostgreSQL] | [order-service] | 事件订阅 |
数据迁移(拆分单体应用时)
| 数据实体 | 当前位置 | 目标服务 | 迁移方式 | 数据量 | 风险 |
|---|---|---|---|---|---|
| [Entity] | [monolith.orders table] | [order-service] | 双写后切换 | [X rows] | [High/Med/Low] |
| [Entity] | [monolith.users table] | [customer-service] | 提取数据并通过 CDC 同步 | [X rows] | [High/Med/Low] |
6. API 契约定义
定义每个服务的接口范围。完整的 OpenAPI 规范另行编写;本节用于确定契约边界。
[service-name] API
基础路径: /api/v1/[resource]
负责团队: [Team]
SLA: [p99 延迟目标、可用性目标]
| 端点 | 方法 | 描述 | 是否需要身份验证 | 速率限制 |
|---|---|---|---|---|
/[resources] | GET | 分页列出 [resources] | 是 | [X req/min] |
/[resources]/{id} | GET | 根据 ID 获取单个 [resource] | 是 | [X req/min] |
/[resources] | POST | 创建新的 [resource] | 是 | [X req/min] |
/[resources]/{id} | PUT | 更新 [resource] | 是 | [X req/min] |
/[resources]/{id} | DELETE | 软删除 [resource] | 是 — 提升权限 | [X req/min] |
[对每个服务重复此内容。]
7. 绞杀者无花果迁移计划(拆分单体应用时)
采用绞杀者无花果模式:逐步提取服务,通过门面路由流量,并逐个淘汰单体应用模块。
迁移阶段
Phase 1: Foundation (Weeks 1–[N])
- Deploy service infrastructure (CI/CD, observability, service mesh)
- Extract lowest-risk, highest-value service first
- Monolith continues to serve all traffic
Phase 2: First Extractions (Weeks [N]–[M])
- Extract P1 services
- API gateway routes selected traffic to new services
- Monolith handles remaining traffic via facade pattern
- Both paths write to shared DB during transition (dual-write)
Phase 3: Core Domain Services (Weeks [M]–[P])
- Extract P1 core domain services
- Data migration for extracted services
- Remove dual-write paths for completed migrations
Phase 4: Monolith Retirement (Weeks [P]–[Q])
- Extract remaining services
- Monolith serves no production traffic
- Decommission monolith infrastructure
分阶段路线图
| 阶段 | 待提取服务 | 迁移方式 | 团队 | 时长 | 依赖项 | 成功标准 |
|---|---|---|---|---|---|---|
| 1 | [service-name] | [绞杀者门面 / 抽象分支 / 事件拦截] | [Team] | [X weeks] | [基础设施就绪,CI/CD 管道] | [流量全部切至新服务,连续 2 周无错误] |
| 2 | [service-name] | [Approach] | [Team] | [X weeks] | [第 1 阶段完成] | [Success metric] |
| 3 | [service-name] | [Approach] | [Team] | [X weeks] | [第 2 阶段完成] | [Success metric] |
回滚计划
为每个迁移阶段定义回滚触发条件和机制:
- 回滚触发条件: 新服务的错误率持续 [Y minutes] 高于 [X%],或 p99 延迟高于 [threshold]
- 回滚机制: API 网关功能标志在 5 分钟内将所有流量切回单体应用路径
- 数据回滚: 切换后继续双写 [X weeks],以便在需要时重放数据
8. 组织对齐(康威定律)
康威定律:系统的架构会映射构建它的组织的沟通结构。设计服务归属时应与团队边界匹配,或者调整团队边界。
| 服务 | 拟定的负责人团队 | 当前团队分配 | 所需变更 |
|---|---|---|---|
| [service-name] | [Team A] | [相同 / 不同] | [无需变更 / 转交给 Team A / 需要新团队] |
| [service-name] | [Team B] | [当前由 Team A 负责] | [转移所有权] |
发现的错位:
- [错位 1:例如,“通知服务目前由两个团队共同负责。将其全部分配给已经负责消息领域的 Team B。”]
- [错位 2:例如,“报告服务由 Data Eng 负责,但使用方是 Product 团队——应建立明确的 API 契约和 SLA。”]
团队拓扑建议:[描述建议的团队结构——流对齐团队、平台团队、赋能团队——以及该结构如何映射到拟定的服务。]
9. 风险登记表
| 风险 | 可能性 | 影响 | 缓解措施 | 负责人 |
|---|---|---|---|---|
| 迁移期间服务间的数据一致性 | 高 | 高 | 采用双写并配合协调任务;关键领域使用事件溯源 | [Name] |
| 分布式事务复杂性(Saga) | 中 | 高 | 从编排式协作开始;仅当编排式协作变得难以管理时再添加协调器 | [Name] |
| 服务网格的运维开销 | 中 | 中 | 初期不使用服务网格;部署 5 个以上服务后再添加 | [Name] |
| 进程内调用改为网络调用带来的延迟 | 中 | 中 | 积极使用缓存;设计读取模型以避免频繁的同步调用 | [Name] |
| 过渡期间的康威定律摩擦 | 高 | 中 | 在开始拆分之前,而非之后,对齐团队结构 | [Name] |
| 过度拆分(纳米服务) | 中 | 高 | 强制执行服务最小规模规则:服务必须证明其自身团队和部署开销是合理的 | [Name] |
| 迁移期间的可观测性缺口 | 高 | 高 | 在首次拆分前部署分布式追踪;建立关联 ID | [Name] |
| [特定上下文的风险] | [等级] | [等级] | [缓解措施] | [负责人] |
对本设计有疑问:[Slack 频道或联系方式]
质量检查
- 限界上下文图是带有关系标签的 ASCII 图,而不是对各上下文的文字描述
- 清单表中的每项服务都有明确的负责人团队,以及清晰的单句职责说明
- 数据所有权矩阵将每个关键实体分配给且仅分配给一个负责服务——不得共享所有权
- 通信模式决策说明了每种交互类型选择同步或异步的原因
- 如果要拆分单体应用,绞杀者无花果迁移计划应包含各阶段的持续时间、依赖关系和成功标准
- 风险登记表至少涵盖:数据一致性、分布式事务和康威定律对齐
- 组织对齐部分将服务映射到团队,并指出需要解决的错位问题
反模式
- 不要在完成领域分析之前定义服务边界——未通过限界上下文映射推导出的服务,会拆错部分,也会错误地耦合部分
- 不要指定多个团队共同负责同一个服务——共同所有权等于无人负责;每个服务都必须有且仅有一个负责团队
- 不要默认所有服务间通信都使用同步 REST 调用——在异步事件可以解耦服务的场景下使用同步调用,会造成级联故障模式
- 没有明确理由时,不要为每个限界上下文提出多个服务——过度拆分(纳米服务)带来的运维开销会超过拆分收益
- 部署分布式追踪之前不要开始迁移——缺乏可观测性就迁移,首次拆分引发生产事故时只能盲目应对