C4 模型示例:Stripe、Netflix、Uber 和 Revolut
你能找到的大多数 C4 模型示例都只是一个玩具系统:一家银行、一个网店、一个只有三个方框加一个数据库的网上银行应用。它们展示了记法,却没有展示真正困难的部分:当真实系统有几百个服务时,决定该省略什么。
本文收集了四个规模更大的 C4 模型示例,每一个都从上下文一直建模到组件:一次 Stripe 刷卡扣款、一次 Netflix 播放请求、一次 Uber 叫车请求,以及一次 Revolut 跨境转账。每个示例都附有第 1 层图、一段关于如何放大到第 2 层和第 3 层的简短说明,以及完整文章的链接。文末还有一个可以直接复制的小示例,以及这四个示例的共同点。
关于资料来源。 这四个示例都来自我们的"Anatomy of"系列,每一个都完全基于相关公司的公开资料:工程博客、技术大会演讲、开源仓库、招聘信息和外部案例研究。它们都不是相关公司的官方架构文档。每篇完整文章都标明了哪些细节是我们推断的,而不是公司明确说明的。
如果你对 C4 模型本身还不熟悉,请先阅读 C4 模型是什么。四篇分层指南会更深入地讲解每种图:系统上下文图、容器图、组件图和代码图。
怎样才算好的 C4 示例
一个 C4 图示例有用,是因为你能从中学到决策,而不只是形状。下面四个示例遵循同样的规则,在看任何一个之前,这些规则都值得先拿走。
追踪一个用户操作。 这些示例没有一个试图记录整个公司。每个示例都选取用户做的一件事(一次扣款、一次播放、一次叫车、一次转账),只画出这个操作涉及的部分。正是这一点,让一个拥有上千个服务的系统能收拢成一页可读的图。
第 1 层控制在十个方框左右。 在系统上下文层面,像 Netflix 这样的公司并不是一千个微服务,而是少数几个产品系统和围绕它们的外部参与者。如果你的第 1 层图需要四十个方框,说明边界画在了错误的高度。
第 2 层只放大一条路径。 容器图展示这一个操作路径上的容器,并标注技术和协议。它不会展示公司运行的所有容器。
第 3 层的放大要有理由。 只有一个容器会画组件图,要么是有意思的工程所在之处,要么是公司公开资料足够详尽、能如实建模的那一个。
用决策来解释方框。 每个示例都在各层之间放了三条简短的架构决策记录(ADR)。图展示存在什么,ADR 说明为什么是这个样子——这正是新人最先会问的问题。
四个示例的对比一览:
| 示例 | 追踪的操作 | 第 1 层 | 第 2 层放大 | 第 3 层放大 |
|---|---|---|---|---|
| Stripe | 一次刷卡扣款(PaymentIntents.create()) |
15 个产品系统 | Payments core | 幂等层 |
| Netflix | 按下播放 | 10 个系统 | Streaming Platform | Cosmos 视频流水线 |
| Uber | 一次叫车请求,从点击到司机接单 | 3 个产品平台、1 个 Marketplace、Foundation 平台 | Marketplace 派单路径 | DISCO 匹配引擎 |
| Revolut | 一笔欧元转英镑的转账 | 8 个产品系统 | Retail Banking 中的转账路径 | Sherlock 反欺诈引擎 |
示例 1:Stripe,一次刷卡扣款

基于 Stripe 的公开资料。并非 Stripe 官方架构文档。
第 1 层。 在系统上下文层面,Stripe 并不是"一个支付 API"。我们的模型呈现出共享同一底座的十五个产品系统:Payments、Connect、Billing、Radar、Issuing、Treasury 等。围绕它们的是商户、持卡人、卡组织、替代支付方式、收单行和发卡行、银行合作伙伴以及 AWS。
第 2 层。 容器图打开 Payments 方框,追踪一次 PaymentIntents.create() 调用:API 网关、位于每个写操作端点之前的幂等层、PaymentIntent 状态机、卡数据保险库、并行运行的 Radar 风险评分、卡组织连接器、账本以及 Webhook 投递。
第 3 层。 组件放大进入幂等层内部,因为这是整个技术栈中公开资料最详尽的部分:请求哈希器、PostgreSQL 中的键存储、阶段执行器,以及一个恢复点追踪器,让重试的请求能从中断处继续执行。
可以借鉴什么。 想学组件图,就研究这个示例。它的第 3 层视图不是一串类名,而是读者可以推理的一连串步骤("每个外部副作用都位于两个恢复点之间")。
完整文章:Anatomy of a Charge:用 C4 建模 Stripe。
示例 2:Netflix,一次播放请求

基于 Netflix 的公开资料。并非 Netflix 官方架构文档。
第 1 层。 从 Netflix 的公开资料中,可以一致地梳理出十个系统:Member Experience、Content Discovery、Streaming Platform、Open Connect、Studio Engineering、Content Engineering、Data Platform、Cloud Platform、Security 和 Ads Platform。外部参与者包括会员设备、托管 Open Connect 设备的 ISP、AWS、DRM 提供商、支付合作伙伴和内容制作公司。
第 2 层。 容器放大打开 Streaming Platform,追踪一次播放请求:Playback API、清单服务、负责 DRM 的许可证服务、消息安全层、EVCache 缓存层以及其后的 Cassandra 集群。清单把设备指向一台 Open Connect 设备,自建 CDN 这一第 1 层决策在这里再次出现。
第 3 层。 组件视图进入视频编码流水线 Cosmos。它并不在请求时的播放路径上(编码发生在影片入库时),文章里也明确说明了这一点。之所以选它,是因为 Netflix 公开的资料足以给每一步命名:检查、复杂度分析、码率阶梯生成、编码、校验和质量评分。
可以借鉴什么。 这是第 1 层"十个而不是一千个"最清晰的示范,也是一个好例子:当第 3 层的放大离开了所追踪的路径时,坦率承认。
完整文章:Anatomy of a Play:用 C4 建模 Netflix。
示例 3:Uber,一次叫车请求

基于 Uber 的公开资料。并非 Uber 官方架构文档。
第 1 层。 在系统上下文层面,Uber 是建立在一个共享 Marketplace 之上的三个产品平台(Mobility、Delivery、Freight),下面还有一层 Foundation 平台:Maps、Payments、身份与风控、通信、机器学习平台、工作流引擎、存储、流处理、可观测性和计算。外部参与者包括乘客、司机、点餐用户、配送员、商家、支付网络、电信运营商和城市监管机构。
第 2 层。 容器放大沿着 Marketplace 的派单路径追踪一次叫车请求:边缘网关、将每次行程作为一个工作流实例运行的行程编排器、匹配引擎、动态定价、ETA 服务、司机状态、存储层以及 Kafka。
第 3 层。 组件视图打开匹配引擎:把坐标转换为 H3 六边形索引的请求归一化器、运力扫描器、环形扩展器、候选排序器、分配求解器、通知分发器,以及一条降级路径。
可以借鉴什么。 这个示例展示了如何在第 1 层画一家平台型公司,而不必画出每一个产品。位于中间的共享 Marketplace,比任何服务清单都更能说明 Uber 的架构。
完整文章:Anatomy of a Ride:用 C4 建模 Uber。
示例 4:Revolut,一笔跨境转账

基于 Revolut 的公开资料。并非 Revolut 官方架构文档。
第 1 层。 公开资料描述了至少八个产品系统:Retail Banking、Business Banking、FX、Wealth and Trading、Credit、FinCrime、Onboarding and KYC,以及带事件总线的核心账本。围绕它们的是卡组织、支付通道(Faster Payments、SEPA、SWIFT)、合作银行、监管机构和 Google Cloud。这张图让一件组织架构图看不出来的事情一目了然:每个产品都有箭头指向 FinCrime,所以它位于所有产品的关键路径上。
第 2 层。 容器放大追踪一笔经由 Retail Banking 的欧元转英镑转账:移动应用、API 边缘层、带显式状态机的转账编排器、基于 PostgreSQL 的复式记账账本、FX 引擎、FinCrime 流水线、每条支付通道各一个的连接器、事件存储以及通知。
第 3 层。 组件视图打开反欺诈引擎 Sherlock:特征组装、内存画像存储、模型服务器、决策策略、夜间重新训练,以及分析师反馈闭环。
可以借鉴什么。 这是四个示例中最完整的一个。它在第 1 层和第 2 层之间加入了分步时间线(延迟数据明确标注为示意值,而非公开数据),还有一节"照抄什么、跳过什么",告诉一个只有十个服务的团队哪些决策值得照搬、哪些不该。
完整文章:Anatomy of a Transfer:用 C4 建模 Revolut。
一个可以直接复制的小示例
上面四个示例是有意选的大系统。大多数系统没那么大,所以这里给出一个涵盖三个实用层级的小型 C4 模型示例:它就是我们在 C4 模型完整指南中通篇使用的电商平台。照搬结构,改掉方框名即可。
第 1 层:系统上下文
[Customer] --> [E-Commerce Platform] : Browses products, places orders
[Warehouse Staff] --> [E-Commerce Platform] : Manages inventory
[E-Commerce Platform] --> [Payment Gateway (Stripe)] : Processes payments
[E-Commerce Platform] --> [Shipping Provider (FedEx API)] : Creates shipments
[E-Commerce Platform] --> [Email Service (SendGrid)] : Sends notifications
两类用户、三个外部系统,以及一个代表你所拥有的一切的方框。
第 2 层:容器
[Single-Page Application (React)] --> [API Gateway (Kong)] : Makes API calls (HTTPS/JSON)
[API Gateway] --> [Order Service (Go)] : Routes requests
[API Gateway] --> [Product Service (Go)] : Routes requests
[API Gateway] --> [User Service (Go)] : Routes requests
[Order Service] --> [Order Database (PostgreSQL)] : Reads/writes orders
[Product Service] --> [Product Database (PostgreSQL)] : Reads/writes products
[User Service] --> [User Database (PostgreSQL)] : Reads/writes users
[Order Service] --> [Message Queue (Kafka)] : Publishes order events
[Notification Service (Go)] --> [Message Queue] : Consumes order events
每个方框都标明技术,每条箭头都标明协议或用途,数据存储也画成容器。
第 3 层:组件(Order Service 内部)
[Order Handler] --> [Order Service] : Delegates business logic
[Order Service] --> [Order Repository] : Persists orders
[Order Service] --> [Payment Client] : Validates payment
[Order Service] --> [Inventory Client] : Checks stock availability
[Order Repository] --> [Order Database (PostgreSQL)] : SQL queries
[Payment Client] --> [Payment Gateway (Stripe)] : HTTPS/REST
[Inventory Client] --> [Product Service] : gRPC
只有一个容器画了组件图,和四个大示例遵循的规则相同。Product 服务和 User 服务只是简单的 CRUD,画出它们的内部,并不会比一份目录清单多告诉你什么。
每个选择背后的理由,请参阅分层指南:系统上下文图应该包含什么、容器图应该包含什么,以及什么时候值得画组件图。这里跳过了第 4 层,原因和大多数团队一样;代码图指南解释了它在什么时候物有所值。
四个示例的共同点
把四个示例放在一起,会发现它们遵循同样的几个习惯。这些都不是 C4 模型本身的规则,而是让这些模型易于阅读的做法。
第 1 层大约十个方框。 Stripe 十五个,Netflix 十个,Revolut 八个,Uber 则是一个 Marketplace 上的三个产品平台加底下的 Foundation 平台。这些公司没有一家是小公司。第 1 层图之所以能保持小巧,是因为它们按产品系统而不是按服务来分组。
第 2 层一条路径。 每张容器图只展示一个操作经过的容器。Stripe 的容器视图里没有 Billing 或 Atlas 的容器,Netflix 的视图里也没有任何 Studio Engineering 的内容。这不是遗漏:那些容器属于另一个操作的另一张图。
第 3 层一个容器,诚实地选择。 组件放大总是去往公开文档足够深入、能画出真实组件的地方。Netflix 那篇文章直接说明了 Cosmos 在请求时并不在播放路径上。一个把这种选择藏起来的示例,教给人的是错误的东西。
外部系统和内部系统同样重要。 卡组织、ISP、支付通道、电信运营商:在四个示例中,最重要的方框里总有几个是公司自己并不拥有的。Revolut 的支付通道连接器就是那种无法靠工程手段消除故障的容器,而图正是让这一点显现出来的东西。
决策紧挨着方框。 每个示例都有三条 ADR,每条 ADR 都解释了一个会让新人感到意外的方框:为什么别的流媒体服务用商业 CDN,而 Netflix 有 Open Connect;为什么 Revolut 没有 Kafka;为什么 Stripe 选择在 MongoDB 之上构建,而不是迁移出去。如果你想知道怎么写这些 ADR,可以看架构决策记录完整指南。
每个方框都有负责人。 每篇文章都在模型最后给出一张归属图:哪个团队拥有哪个系统或容器。正是这一步,让一张图变成有人负责保持其准确的东西。
为你自己的系统建模
要应用这些方法,你并不需要 Stripe 的交易量或 Uber 的服务数量。同样的步骤也适用于一个只有十个服务的系统:
- 选一个重要的用户操作:结账、注册,或者那个会在凌晨 3 点把人叫起来的东西。
- 画第 1 层:把你的系统画成一个方框,加上每一类用户,以及这个操作涉及的每一个外部系统。争取少于十五个方框。
- 为这一个操作画第 2 层:只画它经过的容器,每个都标明技术,每条箭头都标明动词和协议。
- 选一个容器画第 3 层:选新人最难弄懂的那一个,画出它的主要组件。
- 写三条 ADR:针对别人最可能问"为什么是这样?"的三个方框。
- 给每个容器写上团队名。
然后对下一个操作重复。做完三四个操作后,第 2 层的图会开始重叠,而重叠的部分就是你真正的容器图。
这四个示例无法展示的,是六个月之后会发生什么:代码已经变了,图却没有变。archyl 正是围绕这个问题打造的。连接一个仓库,AI 发现会提出系统、容器、组件和关系,由你来审批,而不必从零开始画;之后,漂移评分会持续将模型与代码比对,模型一旦过时你就会知道。
常见问题
什么是好的 C4 模型示例?
好的 C4 模型示例会沿着一个真实的用户操作从第 1 层追踪到第 3 层,并解释其中让人意外的方框。本文的四个示例(Stripe、Netflix、Uber、Revolut)都做到了这一点:第 1 层图大约十个系统,容器图限定在一条路径上,外加一次组件放大。对于小系统,上面的电商示例是一个合适的模板。
哪里可以找到 C4 容器图示例?
四篇完整文章各有一张第 2 层容器图:Stripe 的 Payments core、Netflix 的 Streaming Platform、Uber 的派单路径和 Revolut 的转账路径。如果想看一个带容器和关系表格的小型实战示例,请参阅 C4 容器图指南。
这些是 Stripe、Netflix、Uber 和 Revolut 的官方架构图吗?
不是。每个模型都完全基于相关公司的公开资料,每篇完整文章都标明了哪些细节是推断的,而不是公司明确说明的。它们的目的是展示 C4 模型如何让复杂的技术栈变得易读,而不是记录这些公司如今的实际运行方式。
C4 示例需要全部四个层级吗?
很少需要。这里的四个示例都只画了第 1、2、3 层就停止了。代码层的图会随着每次重构而变化,通常从代码生成比手工绘制更好,这也是大多数真实的 C4 模型止步于组件层的原因。
C4 系统上下文图应该有多少个元素?
没有官方上限。在这些示例中,对于拥有成百上千个服务的公司,第 1 层包含八到十五个系统以及它们的外部参与者。如果你的图需要多得多的元素,很可能是在错误的层级画了容器,或者你需要一张跨多个系统的系统全景(system landscape)视图。
想用 C4 为你自己的系统建模?在 Developer 计划下免费试用 archyl,无需信用卡。继续阅读:什么是 C4 模型?完整指南 | C4 系统上下文图指南 | C4 容器图指南 | C4 组件图指南 | C4 代码图指南