System Design Studio
当用户要求设计、解释或学习某个系统的高层设计(HLD)时使用:"设计Uber"、"Netflix的系统设计"、"支付网关的HLD"、"设计URL缩短器"、"面试准备:设计X"。交付物是一份自包含、可导航的HTML设计文档,作为artifact发布,支持浅色和深色模式,并可选择包含一个交互式画布伴侣。当用户希望获得一个可本地运行的文件时,则将指南和画布作为带选项卡的一个HTML页面提供(§9)。
此仓库中的参考示例展示了质量标准:examples/stock-broker/(默认主题,指南和画布作为独立页面)和 examples/uber/(产品主题,手绘架构SVG,指南和画布在同一文件中)。
1. 确定主题和主题样式
首先对请求进行分类。这决定了内容角度和外观。
- 具名产品或公司(Uber、Netflix、WhatsApp、Swiggy、Zerodha、Airbnb、Spotify、Stripe、Instagram……):指南为"<公司>的系统设计",并且以该产品领域的风格为主题(见§5.2)。在文档各处使用该公司自己的领域词汇(Uber:乘客、司机、行程、调度、动态定价、预计到达时间;Netflix:影片、播放、CDN、编码阶梯;WhatsApp:聊天、投递回执、最后上线时间)。
- 通用系统(URL缩短器、聊天应用、支付网关、速率限制器、通知服务、"一个叫车应用"但未指明公司)或你无法定位的不知名产品:使用默认模板主题(§5.1)。
- 用户指定了样式("让它看起来像Stripe文档"、"简洁极简"):遵循该要求,优先于以上两条规则。
对于具名公司,在设计前进行研究:运行网络搜索,查找其公开的工程博客文章和演讲(例如Uber:H3地理空间索引、Ringpop、Schemaless、Cadence;Netflix:Open Connect、EVCache、Zuul)。使用公开信息,并标注为"据Uber工程博客",在指南的页脚列出来源,并将其他所有内容标记为假设。切勿将推断的设计呈现为该公司的实际内部架构。
2. 构建前进行头脑风暴
在编写任何HTML之前,列出(并通过一条简短消息告知用户)以下几点:
- 该领域的核心洞察:一个边界或理念,如果遗漏,整个设计就会出错。例如:"中介路由,交易所撮合";"支付网关从不持有资金,收单行持有";"Uber的调度是一个秒级延迟预算下的地理空间匹配问题"。将其作为标注放在概述中。
- 不同平面:哪些路径需要强一致性(金钱、订单、库存、预订 → CP),哪些偏向可用性(信息流、搜索、在线状态、位置ping、分析 → AP)。在边缘将它们分开。
- 难题:幂等性、排序、扇出、热键、地理分区、对账、精确一次声明。
- 范围之内 / 范围之外(哪些被视为外部集成)。
- 根据§1决定的主题:使用哪个产品主题,或默认主题。
如果请求确实模糊(哪个产品?面试深度还是生产深度?),询问一个问题;否则开始。
3. 必需部分(按此顺序编号)
- 概述:系统是什么,核心洞察标注,范围之内/之外列表。
- 需求:功能表(领域 → 能力,使用该领域真实的词汇和枚举)和非功能表(属性 → 目标 → 备注)。始终包括延迟、可用性、一致性(每条路径的CP/AP)、持久性、可扩展性、安全性、幂等性。
- 容量估算:假设 → 推导数字的表(用户数、日活跃用户数、峰值并发、写入次数/秒(平均和峰值)、读取次数/秒、扇出出站流量、存储/天)。展示算术过程以便检查;最后用一个标注总结每个平面在哪个轴向上扩展。对于真实公司,尽可能参考其公开报告的规模并注明出处。
- 架构:一个渲染的图表(见§6)加上每个平面和事件骨干的说明文字。
- 组件深度解析:对于每个核心服务:职责、工作机制(状态机、协议、算法)、拥有的数据、故障处理。
- 核心流程生命周期:产品的旗舰端到端流程(Uber:请求行程 → 匹配 → 行程;Netflix:按下播放 → 流媒体播放;WhatsApp:发送消息 → 已投递 → 已读)的步骤表(#、步骤、负责人、状态/事件),以及一个关于同步与异步边界的标注。
- 数据模型与模式:一个ER/类图(见§6),然后是非关系型存储(缓存键模式、时间序列布局、地理索引、搜索索引),然后是事件主题(主题、分区键、事件),附带一个示例事件JSON。不要将原始SQL DDL作为主要模式视图。
- API设计:约定表(认证、幂等性、错误信封、速率限制、分页、版本控制),带有彩色方法标签的端点表,一个关键写入操作的工作请求/响应示例(展示状态码语义,例如异步使用202),状态码表,以及流传输协议(如有,WebSocket/SSE/gRPC流)。
- 一致性与可靠性:每个保证适用的位置,Saga + 补偿,幂等性层,故障场景表。
- 扩展与性能:分片键,无状态自动扩展,分区,缓存,峰值处理。
- 安全与合规:认证/授权,数据保护,监管保留,滥用保护。
- 可观测性:黄金指标,追踪,对账仪表板,告警。
- 权衡:决策 → 选择及原因表,最后以"如果你记得五件事"标注结束。
4. 准确性标准(发布前检查)
- 容量中的每个数字都基于明确假设推导得出,并且内部一致(平均与峰值乘数已说明)。
- 架构图中的每个组件都出现在深度解析或流程中,反之亦然。
- ER图中的每个实体都被某些流程或API使用;每个API的写入路径触及一个真实实体。
- 模式部分中的Kafka/队列主题与架构图中的边标签匹配。
- 涉及金钱时,以复式记账法建模;幂等性键出现在模式(唯一约束)和API(请求头)中。
- 使用领域真实术语(订单类型,协议如FIX/ISO 8583,法规),并在内容是假设时说明。
- 对于具名公司:每个关于其真实技术栈的声明都有来源;其他所有内容都标记为假设。
- 绝不要声称真正的精确一次;描述幂等性 + 对账。
5. 主题,浅色模式和深色模式
每份指南都附带浅色和深色模式:默认遵循读者的系统设置,并且页眉中的切换按钮可以覆盖(每个浏览器记住选择)。在编写页面之前加载 artifact-design 技能。
5.0 令牌系统(两种模式)
所有颜色都是CSS自定义属性。绝不要在规则、SVG或图表中将颜色硬编码;始终使用令牌。在 :root 上定义浅色值,然后是深色值两次(系统偏好设置,除非读者选择了浅色,以及显式的深色选择):
:root{ color-scheme:light; /* light tokens */ }
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){ color-scheme:dark; /* dark tokens */ }
}
:root[data-theme="dark"]{ color-scheme:dark; /* dark tokens, repeated */ }
body{ background:var(--bg); color:var(--ink); }
必需的令牌角色(每个主题在两种模式下都设置所有这些)。使用纯十六进制值(无 rgba(...)),因为图表渲染器会按逗号分割:
| 令牌 | 角色 |
|---|---|
--bg, --surface, --surface-2, --line, --line-soft | 页面、卡片、凸起卡片、边框 |
--ink, --ink-mid, --ink-dim | 标题/粗体文本、正文、说明文字 |
--accent, --accent-ink | 主题的标志性颜色,以及绘制在其上的文本 |
--svc, --svc-bg | 图表中的服务 |
--bus, --bus-bg | 队列/事件总线 |
--ext, --ext-bg | 外部系统 |
--store, --store-bg | 数据存储 |
--ok, --warn, --danger, --info | 标注、方法标签、CP/AP标签 |
--code-bg, --code-ink, --code-key, --code-str, --code-num, --code-com | 代码块 |
--font-display, --font-body, --font-mono | 字体族 |
对比度:正文文本(--ink-mid 在 --bg 和 --surface 上)在两种模式下至少4.5:1;重点文本在 --surface 上至少4.5:1。在深色模式上有效的明亮重点色通常需要在浅色模式下使用较暗的色调,因此分别为每种模式选择值,而不是重用。
在 <head> 中样式表之前放置此内容,以便保存的选择无需闪烁即可应用:
<script>
(function(){var t=null;try{t=localStorage.getItem('sdg-theme')}catch(e){}
if(t==='light'||t==='dark')document.documentElement.dataset.theme=t;})();
</script>
页眉中的切换按钮(<button class="theme-toggle" id="themeToggle" aria-label="切换颜色主题"></button>)及其脚本靠近 <body> 末尾:
<script>
(function(){
var root=document.documentElement, mq=matchMedia('(prefers-color-scheme: dark)');
function current(){return root.dataset.theme||(mq.matches?'dark':'light');}
function label(){var b=document.getElementById('themeToggle');if(b)b.textContent=current()==='dark'?'☀ 浅色':'☾ 深色';}
document.getElementById('themeToggle').addEventListener('click',function(){
var next=current()==='dark'?'light':'dark';root.dataset.theme=next;
try{localStorage.setItem('sdg-theme',next)}catch(e){}
label();document.dispatchEvent(new Event('themechange'));});
mq.addEventListener('change',function(){if(!root.dataset.theme){label();document.dispatchEvent(new Event('themechange'));}});
label();
})();
</script>
5.1 默认模板主题(通用系统)
适用于与具名产品无关的任何系统的内部样式:
- 字体:Space Grotesk(展示用),Inter(正文),JetBrains Mono(标识符、枚举、主题、路径)。
- 深色:午夜蓝底。
--bg #0a0e17,--surface #141b2c,--surface-2 #1a2336,--line #28324e,--ink #eaf0fb,--ink-mid #aab6d2,--ink-dim #7a86a4,--accent #5ec7df,--svc #4fd0e0/--svc-bg #152036,--bus #f3ab54/--bus-bg #241d12,--ext #fb7f95/--ext-bg #2a1622,--store #93a3c0/--store-bg #131b2c。 - 浅色:冷白纸。
--bg #f6f8fc,--surface #ffffff,--surface-2 #eef2f8,--line #d6deea,--ink #0f1729,--ink-mid #45536b,--ink-dim #5f6c85,--accent #0b7287,--svc #0b7287/--svc-bg #e3f3f7,--bus #a35a00/--bus-bg #fdf0dd,--ext #b4234a/--ext-bg #fde7ec,--store #55627a/--store-bg #eef1f6。 - 布局:Hero区域(眉标、标题、包含核心洞察的一段摘要、4张TL;DR卡片:峰值规模、连接数、CP路径、AP路径),然后是两栏正文,桌面端有粘性目录和滚动监听,移动端有浮动"☰ 目录"抽屉。
5.2 产品主题(具名公司)
页面应感觉属于该产品的世界,同时明确保持为独立研究。从产品公开的视觉特征中推导出一整套令牌集(两种模式):其调色板、字体风格、形状语言(锐利 vs 圆润)、密度以及一个标志性图案。起点(近似,唤起而非复制):
| 产品 | 调色板方向 | 字体(免费替代品) | 形状与图案 |
|---|---|---|---|
| Uber | 黑/白单色,一个绿色强调色 | Inter Tight,粗重显示字重 | 锐利边角,高对比度;地图路线线和接载/下车点 |
| Netflix | 近似黑色加深红色强调色;浅色模式暖白+红色 | Bebas Neue(显示),Inter(正文) | 电影大片风格的大标题,海报卡片行 |
| 柔和中性色上的青绿色;深色模式深绿灰色 | Inter / 系统UI | 聊天气泡标注,双勾状态标记 | |
| Airbnb | 暖白配珊瑚色强调色 | Nunito Sans | 大圆角,柔和阴影,友好间距 |
| Spotify | 黑色配亮绿色;浅色模式白色+绿色 | Figtree 或 DM Sans | 药丸形按钮,波形/进度条图案 |
| Stripe | 浅色优先,靛蓝/紫色强调色,柔和渐变 | Inter | 清晰细线,代码块作为一等公民 |
| Swiggy / Zomato | 暖橙色或红色配奶油色;深色棕黑色 | Poppins | 圆角卡片,订单追踪时间线 |
| Zerodha | 干净的白色配蓝色强调色;深色石板蓝 | Inter | 密集数据表,股票行情带 |
对于表中未列出的公司,应用相同方法:识别其标志性颜色、风格和图案,然后构建两种模式。
产品主题的防护栏:
- 受启发,绝不抄袭。 无标志、文字商标、应用图标、吉祥物、屏幕截图或复制的UI界面,以及无专有字体(Uber Move、Netflix Sans、Circular、Cereal):使用免费替代品。图案是通用绘制的(路线线、聊天气泡),而非从产品中提取。
- 标题为研究性质:"Uber系统设计"或"设计一个Uber规模的叫车平台",绝不像是Uber自己发布的。
- 页脚,始终:"独立的学术研究。与<公司>无关或未经其认可。架构根据公开来源和明确假设重建。"以及来源列表。
- 图表、表格、标注和标签仍然使用与默认模板相同的组件结构,通过令牌重新着色。产品主题改变外观,而不是13部分的结构。
5.3 共享组件
- 表格位于圆角滚动容器中;标注(关键/警告/信息/备注)带彩色左边条;方法标签(GET
--ok,POST--info,PUT--warn,DELETE--danger);CP/AP标签。 - 代码块仅用于JSON载荷、键模式和协议消息,带有一个头部栏,标明语言或端点,并使用
--code-*令牌的语法颜色。 - 手机宽度安全:16px内边距,无水平页面滚动(表格和图形在其自己的容器内滚动)。
6. 图表(主题感知)
在 <pre class="mermaid"> 块内使用Mermaid,并用 <figure class="fig"> 包裹,带编号
...
[由于内容被截断,此处结束]