mcpField
E
engineering-system-designer

engineering-system-designer

github.com/peterhdd开发11274 次安装33 周前更新
代码仓库

关于 engineering-system-designer

面向规划新架构或扩展现有系统的工程师,提供系统设计流程、技术决策框架与验证清单,并附容量计算脚本。

主要功能

  1. 01需求梳理与容量估算流程
  2. 02架构和数据存储选型指南
  3. 03故障分析与监控规划
  4. 04容量计算脚本

适用场景

  1. 01设计全新系统
  2. 02评审或扩展现有架构
  3. 03规划从单体迁移到服务

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/peterhdd/agent-skills --skill engineering-system-designer

安装后在 Claude Code 中输入/engineering-system-designer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
code-examples.md
failure-analysis.md
scaling-patterns.md
worked-examples.md
scripts/
capacity_calculator.py

详细介绍

系统设计指南

概述

本指南介绍如何将产品需求转化为可部署、可观测且具有韧性的分布式系统架构。可用于从零开始设计架构、扩展现有系统、设计评审、架构决策记录,或从单体迁移到服务。

设计流程

1. 需求

明确功能需求、非功能目标(延迟、吞吐量、持久性)、读写比例、峰值流量模式和地理分布。如果利益相关者无法提供流量数据,请根据用户数量估算:假设 DAU/MAU 比为 10%,每个会话有 5 个请求,80% 的流量集中在 8 小时内(峰值 = 平均值的 3 倍)。

2. 容量估算

计算 QPS、存储增长和带宽。按 1 倍、5 倍和 10 倍负载进行预测。找出瓶颈资源。使用 scripts/capacity_calculator.py 进行计算。务必展示计算过程——不要在没有推导的情况下直接给出容量结论。

3. 高层架构

梳理组件、数据存储、队列、缓存和外部依赖。定义同步与异步的边界。从尽可能少的组件开始——如果 3 个方框就能解决问题,就不要画 7 个。

4. 组件深入分析

说明技术选型并给出理由。为每个存储定义分区、复制、一致性模型和缓存失效策略。每项技术选型都必须回答:“为什么选它,而不是更简单的替代方案?”

5. 数据模型和 API 设计

针对主要访问模式设计架构。定义 API 契约,包括错误代码和速率限制。规划迁移策略。每张表都必须列出其最常见的 3 种查询模式及预期延迟。

6. 故障模式

列出每个组件的故障及其影响范围。定义熔断器、重试、超时和回退方案。对于每种故障模式,说明:会发生什么故障、会影响谁、如何检测,以及自动恢复机制是什么。

7. 监控

明确上线前所需的指标、告警和仪表板。每个 SLO 都必须对应一个告警。每个告警都必须附有运行手册链接。

决策框架

SQL 与 NoSQL
  • 当你需要跨多个实体执行事务、用于报告的复杂联接,或强制执行严格的架构时,使用 SQL(默认选用 PostgreSQL)。
  • 当访问模式为键值查询、架构频繁变化,或需要超越单节点能力的水平写入扩展时,使用 NoSQL。
  • 具体阈值: <10TB 且为关系型访问模式 = PostgreSQL。键值型,且延迟 <10ms、QPS >100k = Redis 或 DynamoDB。架构灵活且容量 <50TB 的文档存储 = MongoDB。容量 >1PB 或每秒写入 >1M 的宽列存储或时间序列 = Cassandra 或 ScyllaDB。全文搜索 = 在主存储旁使用 Elasticsearch/OpenSearch(绝不能将其作为事实来源)。
数据库扩展阈值
  • 单个 PostgreSQL: 在现代硬件上可处理高达约 10k QPS 的读取和约 5k QPS 的写入。如果读操作占主导(读取 >80%),请先添加只读副本。
  • 只读副本: 当读取 QPS 超过单节点容量,或读取 p95 延迟 >50ms 时添加。预计复制延迟为 1-5s——针对只读副本上的读取,按最终一致性设计。
  • 连接池(PgBouncer): 当连接数超过 200 时必须使用。绝不能让应用程序无限制地打开连接。
  • 分片: 当单节点写入 QPS 不足,或单节点存储超过约 5TB 时必须分片。按基数最高、查询最多的列选择分片键。使用基于哈希的分片实现均匀分布;对于时间序列或地理数据,使用基于范围的分片。
  • 使用 Redis 缓存: 当同一查询每分钟运行 >100 次且结果相同时添加。使用旁路缓存模式。明确设置 TTL——缓存不得没有过期时间。如果缓存命中率 <80%,说明缓存没有起到作用——删除缓存或修正键的设计。
同步 vs. 异步
  • 当调用方需要结果才能继续,且延迟可控制在 200ms 以内时,使用同步通信。
  • 当操作可以稍后完成、需要应对流量峰值,或下游服务的延迟不稳定时,使用异步消息传递。
  • 队列选择: 简单任务队列使用 SQS(消息 <256KB,至少投递一次)。需要路由或优先级队列且吞吐量 <10k 条消息/秒时使用 RabbitMQ。需要事件流、>10k 条消息/秒、重放能力或多个消费者读取同一数据流时使用 Kafka。
单体 vs. 微服务
  • 从单体架构开始。只有在存在明确的扩展瓶颈、独立部署节奏的要求,或团队所有权边界导致合并冲突时,才拆分出服务。
  • 一次最多拆分一个服务。验证运维准备就绪后,再进行下一次拆分。
  • 团队规模规则: <10 名工程师 = 单体。10-50 名工程师 = 具有清晰领域边界的模块化单体。>50 名工程师 = 按团队边界划分的微服务。架构的发展速度绝不能超出运维能力。
负载均衡与 CDN
  • <1k QPS:单个实例配合健康检查即可满足需求。
  • 1k-50k QPS:使用应用负载均衡器和自动扩缩组(最少 2 个实例;当 CPU >60% 或请求数达到阈值时扩容)。
  • 50k QPS:为静态资源和可缓存的 API 响应添加 CDN(CloudFront/Cloudflare)。如果 >80% 的流量可缓存,仅靠 CDN 也可能足以应对该规模。

  • 如果全球用户分布在 >2 个大洲:采用多区域部署,并使用基于延迟的 Route 53 路由或 Cloudflare 全球负载均衡。
速率限制
  • 对所有公共端点在 API 网关处实施速率限制。默认值:每位用户 100 req/min,每个 IP 1000 req/min。
  • 对写入密集型端点(POST/PUT/DELETE):每位用户 10-30 req/min。
  • 对高成本操作(搜索、报告、导出):每位用户 5 req/min。
  • 返回 429 Too Many Requests 和 Retry-After 标头。记录触发速率限制的请求,以便检测滥用行为。

设计原则

  • 了解 CAP 定理: 明确系统优先考虑一致性、可用性和分区容错性中的哪两项,并明确记录取舍。如果无法说明设计中每个数据存储的 CAP 取舍,设计就不完整。
  • 从简单开始: 以满足需求所需的最少组件开始。只有测量结果表明确有需要时才增加复杂性。新增组件必须能解决明确的瓶颈——“以后可能用得上”并非充分理由。
  • 为故障而设计: 每个组件都会发生故障。在编写代码之前,先定义故障发生时的处理方式。如果未分析某个组件的故障模式,就还不能将其用于生产环境。
  • 优先选择成熟技术: 除非存在明确且量化的优势(吞吐量提升 >2 倍、成本降低 >50%,或可实现成熟方案无法实现的功能),否则应选择经过充分验证、运维记录良好的工具,而不是新颖的替代方案。
  • 让决策可逆: 优先选择可独立替换、扩展或移除组件,而无需重写整个系统的设计。如果替换某个组件需要修改 >3 个服务,请增加一层抽象。

估算速查

  • 存储: 1M 用户,每人平均 10 个字段,每个字段 100 字节 = 约 1GB 原始数据。索引和开销按 3 倍计算。
  • 带宽: 1 次 API 调用的平均响应为 5KB,在 10k QPS 下 = 50MB/s = 400Mbps。预留 2 倍余量。
  • 根据 DAU 估算 QPS: DAU * 每个会话的平均请求数 / 高峰时段的秒数。峰值 = 平均值的 3 倍。
  • 复制: 至少需要 3 个副本以确保持久性。跨区域复制会增加 50-200ms 延迟。
  • 连接数估算: 每个 PostgreSQL 连接约占用 10MB RAM。100 个连接仅连接本身就需要 1GB。如果需要 >200 个连接,请使用 PgBouncer。

参考:系统设计文档模板

每份系统设计文档都应包含:

  • 问题陈述和功能需求。
  • 包含具体数值目标的非功能需求。
  • 展示计算过程的容量估算。
  • 高层架构图说明(组件、数据流、协议)。
  • 包含访问模式和索引策略的数据模型。
  • 所有服务边界的 API 契约。
  • 每个组件的故障模式分析。
  • 包含具体指标和告警阈值的监控计划。
  • 上线时和规模扩大到 10 倍时的基础设施成本估算。

自我验证流程

完成系统设计后,在提交前根据以下检查项进行验证:

  • 每个组件都有故障模式分析。如果无法说明组件宕机时会发生什么,那么设计就不完整。
  • 每个数据存储都明确记录了 CAP 取舍。必须说明“我们选择 AP 而非 CP,因为……”。
  • 展示 1 倍、5 倍和 10 倍规模下的容量计算。如果任何数字是未经推导而假设的,请将其标记为假设。
  • 每项技术选型都要回答:“为什么选它而不是更简单的替代方案?”如果答案是“因为我熟悉它”,这对单体架构来说可以接受,但对分布式系统不行。
  • 每个服务边界都有 API 契约,包含请求/响应模式、错误代码和速率限制。
  • 监控计划要列出具体指标名称、告警阈值和运行手册引用,而不能只写“我们会监控”。
  • 交叉核对:重新阅读功能需求,确认每一项都对应至少一个组件。如果某项需求没有任何组件支持,设计就存在缺口。
  • 必须提供成本估算。如果基础设施成本超过每月 10,000 美元,请说明每个主要成本项的合理性。

故障恢复

  • 设计未达到延迟目标:找出调用链中最长的路径。先在瓶颈处添加缓存。如果仍不够,则改用异步处理,或对数据模型进行反规范化。切勿通过增加组件来解决延迟问题——应减少跳数。
  • 写入吞吐量超过单节点容量:确认瓶颈确实存在(对热点查询运行 EXPLAIN ANALYZE)。如果确认存在,则按基数最高的写入键分片。如果写入模式是仅追加(日志、事件),则使用 Kafka 或时序数据库,而不是对关系型存储进行分片。
  • 设计评审发现遗漏的需求:不要打补丁。回到第 1 步(需求),更新容量估算,并重新评估高层架构。靠不断追加功能扩展的设计会在负载下崩溃。
  • 利益相关者提出与设计原则相矛盾的功能:明确记录取舍。“添加实时同步需要将此存储从 CP 转为 AP。这意味着用户看到的数据最长可能过时 5 秒。”让利益相关者依据明确的取舍数据做决定,而不是依据模糊的顾虑。
  • 估算成本过高:从边缘开始逐步削减。移除 CDN → 减少副本数量 → 缩小实例规格 → 简化为单体架构。切勿为了节省成本而削减监控或备份。

现有系统评估

当需要重新设计或扩展现有系统时:

  1. 先测量,再提出方案 — 获取当前的 QPS、p50/p95/p99 延迟、错误率和存储增长率。基于猜测设计的方案会失败。
  2. 找出真正的瓶颈 — 进行性能分析,不要猜测。瓶颈很少出现在人们以为的位置。检查:慢查询(pg_stat_statements)、连接饱和度、CPU 与 I/O 瓶颈、缓存命中率。
  3. 找到关键的 20% — 哪一项改动可以解决 80% 的扩展问题?从这里开始。常见答案:添加索引、添加缓存、添加只读副本、将耗时任务改为异步执行。
  4. 保留有效的部分 — 如果当前系统能顺利处理 80% 的流量,就不要重写。只扩展出问题的 20%。
  5. 渐进式迁移 — 采用绞杀者无花果模式:将新流量路由到新系统,再逐步迁移旧流量。对于服务超过 1k QPS 的系统,绝不要一次性切换。

脚本

  • scripts/capacity_calculator.py -- 根据流量假设计算 QPS、存储和带宽。运行时使用 --help 查看选项。

请参阅代码示例,了解完整的实现模式,包括容量估算、API 契约、带分片的数据库架构和断路器。

请参阅实战示例,查看 URL 缩短器和类似 WhatsApp 的聊天系统的完整系统设计演练,涵盖从需求到生产架构的内容。

请参阅故障分析,获取故障模式分析模板、缓存策略比较、负载削减、舱壁模式和混沌工程检查清单。

请参阅扩展模式,了解一致性哈希、数据库分片、CQRS、速率限制、背压处理和 AWS 成本估算模板。

评论

支持 Markdown