zeroz-lab/unified-skills · Archived

build-backend-service-patterns

服务架构模式——分层、通信、韧性。当需要设计后端服务架构、跨服务通信或处理分布式问题,或提到"微服务""重试""熔断

Installation

$ npx skills add zeroz-lab/unified-skills --skill build-backend-service-patterns

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from zeroz-lab/unified-skills · top by installs.

npx skills add zeroz-lab/unified-skills

Browse all from zeroz-lab/unified-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 16
License MIT
Default branch master
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,206 B
  • docs SUMMARY.md 202 B

History

  1. First recorded snapshot · 2 installs

SKILL.md

Service Patterns — 服务架构模式

入口/出口

  • 入口: 涉及多个服务/模块的边界设计、通信模式选择、韧性策略
  • 出口: 模式选择记录 + 接口定义 + 韧性配置
  • 指向: 架构确定后进入 build-backend-api-design(定义具体接口)
  • 输出路径: verify-workflow-review(下游验证技能)
  • 前置加载: CANON.md

何时不使用

  • 只是在单服务内部实现一个清晰函数或端点
  • 服务边界、通信方式和容错策略已经由 spec/ADR 明确
  • 问题集中在具体 API 合约或数据库 schema,而不是服务架构

服务分层

Presentation  →  API Handler / Controller(HTTP、验证、序列化)
     │
Business      →  Service(领域逻辑、规则、工作流)
     │
Data          →  Repository / Adapter(数据访问、外部 API 封装)
     │
Infrastructure →  DB、Cache、Queue、外部服务

依赖方向: 上层依赖下层,依层不跨层。Business 不直接 import HTTP 框架类型。

通信模式

模式 适用场景 示例
同步 Request-Response 需要立即结果、强一致性 创建订单 → 返回订单号
异步 Message Queue 可延迟、高吞吐 订单创建后发送邮件通知
Event-Driven Pub/Sub 多消费者、解耦 订单完成 → (通知服务 + 分析服务 + 积分服务)
Saga (编排) 跨服务长事务 下单 → 扣库存 → 扣款 → 通知(任一步失败 = 补偿回滚)

选择原则:

需要立即响应 + 强一致?→ 同步
可延迟 + 需要韧性?  → 异步
多消费者 + 解耦?   → Event-Driven
跨服务长事务?      → Saga

韧性模式

重试与退避

async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (attempt === maxRetries) throw err;
      const delay = Math.pow(2, attempt) * 100;  // 100ms → 200ms → 400ms
      await sleep(delay);
    }
  }
  throw new Error('unreachable');
}

断路器

状态机:
  CLOSED → (连续失败 N 次) → OPEN(立即失败,不调用)
  OPEN → (等待 timeout) → HALF_OPEN(尝试一次)
  HALF_OPEN → 成功 → CLOSED | 失败 → OPEN

断路器保护下游服务不被雪崩淹没。 当调用已经反复失败时,快速失败 > 继续重试拖死上游。

幂等性

// 每个写操作需要幂等键
interface CreateOrderRequest {
  idempotencyKey: string;  // 客户端生成 UUID
  items: OrderItem[];
}

// 服务端: 相同幂等键 → 返回相同结果(不重复创建)
async function createOrder(req: CreateOrderRequest): Promise<Order> {
  const existing = await db.orders.findBy({ idempotencyKey: req.idempotencyKey });
  if (existing) return existing;
  return db.orders.create(req);
}

任何涉及支付的端点必须有幂等键。 网络重试 + 重复扣款 = 灾难。

模式选择

需求 模式 复杂度代价
CRUD 围绕单一实体 Repository + Service
读/写负载不对称 CQRS(读写分离)
跨服务事务 Saga
复杂业务规则链 Chain of Responsibility / Pipeline
多策略可切换 Strategy Pattern
领域逻辑密集 Domain-Driven(Entity + Value Object + Aggregate) 中-高

原则: 从最简单的模式开始。当代码变复杂因为模式不够时才升级,不因为"如此"。

错误处理

// 区分可恢复错误 vs 不可恢复错误
class RetryableError extends Error { /* 网络超时、503 */ }
class FatalError extends Error { /* 验证失败、404 */ }

async function handleServiceCall(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn();
  } catch (err) {
    if (err instanceof RetryableError) {
      return withRetry(fn);
    }
    throw err;  // Fatal — 上层处理
  }
}

常见说辞

说辞 现实 后果
"以后需要时再加重试" 网络是不确定的。从第一条跨服务调用开始就加重试。 无重试 → 单次网络抖动导致请求失败率从 0.1% 飙升到 5-10%,生产故障排查时间 2-8 小时
"断路器太复杂,直接重试" 一直重试失败的服务 = 拖着上游一起死。断路器是保护装置。 无断路器 → 下游宕机时上游持续重试耗尽线程池,级联故障扩散到 3-5 个服务
"幂等性以后补" 有支付的系统从第一天就需要。补幂等性需要改 API 合约。 缺幂等键 → 网络重试导致重复扣款/重复创建,单次事故赔偿成本 > 开发成本 10 倍
"同步耦合没关系,微服务间调用很快" 现在快。调用链 lengthens,故障面扩大。能不耦合就不耦合。 同步链 > 3 层 → 平均故障恢复时间翻倍,任何一层超时导致整条链失败
"选 CQRS,虽然简单但万一以后要读扩展" 为"万一"增加复杂度 = 过早工程化。简单需求简单方案。 过早 CQRS → 读写模型同步延迟 bug、运维复杂度提升 3-5 倍,90% 项目不需要

验证失败处理

失败场景 处理方式
跨服务 HTTP 调用无重试和超时 停止,为每个跨服务调用添加 withRetry + timeout 配置后再继续
支付相关端点缺少幂等键 停止,添加 idempotencyKey 字段到 API 合约,服务端实现幂等检查后再继续
队列消费者无死信队列 添加 DLQ 配置,失败消息进入 DLQ 而非反复消费,避免队列堵塞
同步调用链 > 3 层 重构为异步解耦或引入 Saga 编排,不允许串行穿透超过 3 个服务
服务边界按技术层而非业务领域划分 重画服务边界图,按业务领域(如订单、支付、用户)重新划分

好坏示例

✅ Good: 最简模式 + 韧性完整

订单创建流程:
- API Handler → 调用 OrderService.createOrder()
- OrderService → 写入 DB + 发事件到 Queue(异步解耦)
- 邮件服务消费 Queue 事件(异步,不阻塞订单创建)

韧性配置:
- OrderService → DB: withRetry(3, exponentialBackoff)
- OrderService → Queue: 断路器(5 次连续失败打开)
- createOrder API: idempotencyKey 必填
- Queue 消费者: 死信队列(失败 3 次进入 DLQ)

模式选择: Repository + Service(最简,匹配 CRUD 围绕单一实体需求)

❌ Bad: 过早工程化 + 缺韧性

订单创建流程:
- API → OrderService → InventoryService → PaymentService → NotificationService
  (同步链 4 层,任何一层超时整条链失败)

韧性配置: (未配置重试、断路器、幂等键)

模式选择: CQRS + Saga + Event Sourcing
  (当前只需 CRUD,过早引入 3 个高复杂度模式)

红旗 — STOP

  • 单体拆成微服务但没有定义故障模式(网络分区、超时、下游宕机)
  • 没有重试/断路器的跨服务 HTTP 调用
  • 支付相关端点缺少幂等键
  • 队列消费者没有死信队列(DLQ)—— 坏消息反复消费
  • 同步调用链 > 3 层(请求串行穿透多个服务)
  • 从表现层直接调用数据层(跳过 Business/Service)

输出模板

服务架构设计完成后,应在 ADR 或 03-plan.md 中记录以下结构:

## Service Architecture — [功能名称]

### 服务边界
| 服务 | 业务领域 | 负责范围 |
|------|---------|---------|
| [服务 A] | [领域] | [职责描述] |
| [服务 B] | [领域] | [职责描述] |

### 通信模式
| 调用路径 | 模式 | 理由 |
|---------|------|------|
| [A → B] | 同步 / 异步 / Event / Saga | [需要立即结果 / 可延迟 / 多消费者 / 跨服务长事务] |

### 韧性配置
| 调用路径 | 重试策略 | 断路器 | 幂等性 | 超时 |
|---------|---------|--------|-------|------|
| [A → B] | [次数 + 退避] | [阈值] | [是否需要] | [毫秒值] |

| 队列 | 消费者 | 死信队列 | 重试次数 |
|------|--------|---------|---------|
| [Queue A] | [消费者] | [DLQ 配置] | [次数] |

### 模式选择
| 需求 | 选定模式 | 复杂度代价 | 选择理由 |
|------|---------|-----------|---------|
| [需求描述] | [模式名] | [低/中/高] | [当前需求最简方案] |

### 故障模式
| 单点 | 降级方案 | 影响范围 |
|------|---------|---------|
| [单点描述] | [降级策略] | [受影响服务/用户] |

验证清单

  • 服务边界清晰(按业务领域,不按技术层)
  • 跨服务调用有重试和超时配置
  • 支付/扣款相关有幂等键
  • 异步消费者有死信队列
  • 故障模式已识别(单点在哪?降级方案?)
  • 选择的是当前需要的最简模式