架构模式快速参考指南

构建具有韧性、可扩展的分布式系统需要针对特定挑战选择正确的架构模式。本指南提供快速参考,帮助您根据问题领域选择最合适的模式,并附上每个模式的详细说明链接。

模式选择快速参考

使用此表格快速识别哪个模式能解决您的特定挑战:

您的挑战建议模式使用时机
服务调用超时异步请求-回复操作时间超过 HTTP 超时限制
服务持续失败断路器防止不可用的服务造成连锁故障
暂时性网络故障重试处理快速恢复的暂时性故障
一个服务影响其他服务舱壁隔离资源以控制故障范围
跨服务业务事务Saga 模式通过补偿机制编排跨服务的长时事务
需要撤销多步操作补偿事务通过语义反向操作回滚跨服务的部分工作
突发流量压垮服务基于队列的负载均衡在生产者和消费者之间以队列缓冲,平滑突发尖峰
本地写入 + 事件发布的原子性发件箱与本地数据库事务一起保证事件可靠发布
API 限流错误速率限制控制对限流服务的请求速率
遗留系统集成防腐层保护干净架构免受遗留系统影响
查询性能缓慢物化视图预先计算复杂查询以加快读取速度
高频重复读取相同数据缓存旁路按需将数据加载到缓存以缓解读压力
需要按非主键字段快速查找索引表为查询频繁的字段建立二级索引
读写负载差异显著CQRS分离读模型与写模型以独立扩展
大型消息负载提领检查通过外部存储数据来减少消息大小
迁移遗留系统绞杀者无花果逐步用现代系统替换遗留系统
跨领域关注点边车在不修改应用程序的情况下新增功能
数据库可扩展性分片将数据分散到多个数据库
多个 API 调用网关聚合将多个后端调用合并为一个
多个服务版本或端点网关路由通过单一端点将请求路由到多个服务
事件分发发布-订阅解耦事件生产者与消费者
服务健康监控健康端点监控主动检测服务故障
需要单一协调者领导者选举通过选举一个实例为领导者来协调分布式工作
配置频繁变更外部配置存储在部署包外集中化管理配置
跨服务身份验证联合身份集中化身份验证和授权

模式分类

架构模式可以根据它们解决的问题进行分组:

🛡️ 韧性模式

帮助系统优雅处理故障的模式: 断路器:通过暂时阻止对失败服务的调用来防止连锁故障。就像电路断路器一样,当故障超过阈值时会”跳闸”,让系统快速失败并优雅恢复。 重试:自动重试失败的操作以处理暂时性故障。使用指数退避等策略来避免压垮已经承受压力的服务。 舱壁:将资源隔离到独立的池中,防止一个失败的组件消耗所有资源。以船舱命名,用于控制进水。 Saga 模式:通过正向操作和补偿操作,跨服务编排长时业务事务。与舱壁配套使用:舱壁隔离单个服务内部的故障;Saga 跨服务协调恢复。 [补偿事务]:撤销由一系列步骤共同完成的最终一致操作的工作。Saga 模式的基础:每个 Saga 步骤都需要在后续步骤失败时具备语义反向操作。 [基于队列的负载均衡]:在任务与它调用的服务之间引入队列作为缓冲,将任务与服务解耦。让消费者按自身节奏处理,平滑突发重负载,防止限流并提升可用性。 [发件箱]:在业务写入的同一本地事务中将待发布消息存入”发件箱”表,再由独立进程读取发件箱并发布到消息总线。解决当 Saga 事件必须与状态变更原子性发出时的双写问题。

💡组合韧性模式

这些模式最好一起使用:重试处理暂时性故障,断路器防止压垮失败的服务,舱壁控制故障的爆炸半径。Saga 模式在跨服务场景下与之互补——编排能够承受部分故障的多步事务。基于队列的负载均衡在脆弱依赖上游吸收突发流量,发件箱保证 Saga 事件与本地数据库事务可靠一同发布。

⚡ 性能模式

优化系统性能和响应性的模式: 异步请求-回复:将长时间运行的操作与即时响应解耦,防止超时并改善用户体验。 物化视图:预先计算并存储查询结果,避免在读取时进行昂贵的计算。适合复杂的聚合和报表。 [缓存旁路]:按需将数据从底层数据存储加载到缓存;应用程序优先从缓存读取,未命中则回退到数据存储并回填缓存。最常见的读侧优化——通常在考虑物化视图之前使用。 [索引表]:为数据存储中查询频繁引用、但主键未覆盖的字段创建二级索引。当查询模式具有选择性时,比物化视图更易于构建和维护。 [CQRS]:将读操作与写操作分离为不同的模型(往往使用不同存储)。读侧可独立于写侧扩展,读模型可以针对查询速度进行反规范化,代价是写侧的最终一致性。 提领检查:通过将大型数据存储在外部并仅传递引用来减少消息负载大小。改善消息系统性能并降低成本。 分片:将数据分散到多个数据库以提高可扩展性和性能。每个分片处理总数据的一个子集。

🔄 集成模式

促进系统间通信的模式: 防腐层:在具有不同语义的系统之间提供转换层,保护您的干净架构免受遗留系统怪癖的影响。 网关聚合:将多个后端服务调用合并为单一请求,减少客户端复杂性和网络开销。 [网关路由]:通过单一端点将请求路由到多个服务之一。与网关聚合和网关卸载自然搭配,共同构成完整的 API 网关。 发布-订阅:启用异步事件驱动通信,发布者不需要知道订阅者。 联合身份:将身份验证委派给外部身份提供者,实现跨多个系统的单点登录。

🎯 运营模式

改善系统运营和管理的模式: 速率限制:控制发送到服务的请求速率,避免限流错误并优化吞吐量。 健康端点监控:公开健康检查端点以进行主动监控和自动恢复。 边车:在应用程序旁部署辅助组件,处理日志记录、监控和配置等跨领域关注点。 [领导者选举]:从一组分布式任务实例中选举一个实例担任领导者,由其协调其他实例的工作。适用于需要一个单一协调者(例如调度或分片分配)但没有永久指定实例的场景。 [外部配置存储]:将配置信息从应用程序部署包中移出,集中存放到独立位置。让配置能够不重新部署即可变更,并支持环境特定值、特性开关和密钥。

🏗️ 迁移模式

支持系统现代化的模式: 绞杀者无花果:通过逐步将功能迁移到新实现来逐步替换遗留系统。以缠绕并最终替换宿主的无花果树命名。

决策流程图:选择正确的模式

使用此流程图导航到最适合您情况的模式:

graph TD Start[您的挑战是什么?] --> Q1{服务<br/>可用性?} Q1 -->|重复失败| CB[断路器] Q1 -->|暂时性故障| Retry[重试模式] Q1 -->|一个影响其他| Bulkhead[舱壁] Q1 -->|多服务协作| SagaNode[Saga] Q1 -->|需要撤销操作| CT[补偿事务] Q1 -->|突发流量| QBLL[基于队列的负载均衡] Q1 -->|写入+发布原子性| OB[发件箱] Q1 -->|性能| Q2{什么类型?} Q2 -->|长时间操作| Async[异步请求-回复] Q2 -->|查询缓慢| MV[物化视图] Q2 -->|高频读取| CA[缓存旁路] Q2 -->|按字段查找| IT[索引表] Q2 -->|读写分离| CQRSNode[CQRS] Q2 -->|大型消息| CC[提领检查] Q2 -->|数据库规模| Shard[分片] Q1 -->|集成| Q3{什么需求?} Q3 -->|遗留系统| ACL[防腐层] Q3 -->|多个调用| GA[网关聚合] Q3 -->|多端点| GR[网关路由] Q3 -->|事件分发| PubSub[发布-订阅] Q3 -->|身份验证| FI[联合身份] Q1 -->|运营| Q4{什么方面?} Q4 -->|限流| RL[速率限制] Q4 -->|监控| HEM[健康端点] Q4 -->|跨领域| Sidecar[边车] Q4 -->|单一协调者| LE[领导者选举] Q4 -->|配置变更| ECS[外部配置存储] Q1 -->|迁移| SF[绞杀者无花果] style CB fill:#ff6b6b style Retry fill:#ff6b6b style Bulkhead fill:#ff6b6b style SagaNode fill:#ff6b6b style CT fill:#ff6b6b style QBLL fill:#ff6b6b style OB fill:#ff6b6b style Async fill:#51cf66 style MV fill:#51cf66 style CA fill:#51cf66 style IT fill:#51cf66 style CQRSNode fill:#51cf66 style CC fill:#51cf66 style Shard fill:#51cf66 style ACL fill:#4dabf7 style GA fill:#4dabf7 style GR fill:#4dabf7 style PubSub fill:#4dabf7 style FI fill:#4dabf7 style RL fill:#ffd43b style HEM fill:#ffd43b style Sidecar fill:#ffd43b style LE fill:#ffd43b style ECS fill:#ffd43b style SF fill:#a78bfa

模式比较矩阵

跨关键维度比较模式:

{ "title": { "text": "模式复杂度 vs 影响" }, "tooltip": { "trigger": "item", "formatter": "{b}<br/>复杂度: {c0}<br/>影响: {c1}" }, "xAxis": { "type": "value", "name": "实现复杂度", "min": 0, "max": 10 }, "yAxis": { "type": "value", "name": "系统影响", "min": 0, "max": 10 }, "series": [{ "type": "scatter", "symbolSize": 20, "data": [ {"name": "重试", "value": [2, 7]}, {"name": "断路器", "value": [4, 8]}, {"name": "舱壁", "value": [5, 8]}, {"name": "补偿事务", "value": [5, 8]}, {"name": "基于队列的负载均衡", "value": [5, 7]}, {"name": "发件箱", "value": [4, 7]}, {"name": "速率限制", "value": [6, 7]}, {"name": "防腐层", "value": [7, 9]}, {"name": "异步请求-回复", "value": [6, 8]}, {"name": "物化视图", "value": [5, 7]}, {"name": "缓存旁路", "value": [3, 7]}, {"name": "索引表", "value": [4, 7]}, {"name": "CQRS", "value": [8, 9]}, {"name": "提领检查", "value": [3, 6]}, {"name": "绞杀者无花果", "value": [8, 9]}, {"name": "边车", "value": [4, 6]}, {"name": "分片", "value": [9, 9]}, {"name": "网关聚合", "value": [5, 7]}, {"name": "网关路由", "value": [4, 7]}, {"name": "发布-订阅", "value": [6, 8]}, {"name": "健康端点", "value": [2, 6]}, {"name": "领导者选举", "value": [7, 7]}, {"name": "外部配置存储", "value": [3, 6]}, {"name": "联合身份", "value": [7, 8]}, {"name": "Saga 模式", "value": [7, 9]} ], "label": { "show": true, "position": "top", "formatter": "{b}" } }] }

模式组合

许多实际系统结合多个模式以提供全面的解决方案:

韧性微服务堆栈

这四个——断路器重试舱壁健康端点——是「每一次同步服务间调用都被它们包着」这套经典集合。每个模式针对的都是其它三个解决不了的失败模式,并按下图顺序分层:

模式针对的失败模式分层
健康端点盲目运行——无法区分瞬时抖动和持续故障检测(喂给其它三者)
断路器连锁故障——一个慢下游拖垮整张网保护(调用前的闸门)
重试瞬时抖动——网络抖动、GC 暂停、短时过载恢复(包住调用)
舱壁资源饥饿——一个吵闹邻居耗尽共享资源隔离(每个下游的资源上限)
flowchart TB Caller[调用方] Caller --> Bulkhead[舱壁<br/>按下游限线程池] Bulkhead --> Breaker{断路器<br/>开 / 半开 / 关} Breaker -->|关| Retry[重试循环<br/>指数退避<br/>幂等] Retry --> Call[服务调用] Breaker -->|开| FailFast[快速失败] Health[健康端点<br/>由监控探测] Health -.喂给状态.-> Breaker style Bulkhead fill:#c8e6c9 style Breaker fill:#fff9c4 style Retry fill:#e1f5ff style Health fill:#f5f5f5

从内往外读:舱壁给这个下游设了资源上限;断路器决定要不要继续;重试在闭合回路里处理每次调用的瞬时抖动;健康端点由监控轮询,喂给断路器状态机的信号。

  • 断路器:防止连锁故障
  • 重试:处理暂时性故障
  • 舱壁:隔离资源
  • 健康端点:启用监控

高性能 API 网关

这三个——速率限制网关聚合异步请求-回复——构成「高吞吐量公开 API 边缘」的经典集合。每个模式针对的都是其它两个解决不了的关注点:拒绝、组合还是时延缓解。它们沿请求流分层,如下图所示:

模式针对的失败模式在请求流中的位置
速率限制后端过载——行为异常的客户端或突发流量打挂上游入口闸门(先拒绝再做事)
网关聚合客户端来回过多——每次一屏要 N 次往返,移动端和弱网环境尤其痛苦组合(扇出再合并)
异步请求-回复阻塞——一次慢下游调用就卡住线程并占住一条客户端连接时延缓解(慢调用返回 202 + 轮询令牌)
flowchart TB Client[客户端] Client --> RL[速率限制<br/>按客户端限额<br/>先拒后放] RL --> GA[网关聚合<br/>扇出 N 个调用<br/>合并为 1 个响应] GA -->|快速调用<br/>同步| Sync[同步处理<br/>立即响应] GA -->|慢速调用<br/>> 阈值| Async[异步请求-回复<br/>202 + 轮询令牌<br/>Claim-Check 风格] Sync --> Backends[后端] Async --> Backends style RL fill:#ffcdd2 style GA fill:#c8e6c9 style Async fill:#e1f5ff

从上往下读这张图:速率限制是最外层闸门——先拒绝,绝不让恶意流量到达组合层;网关聚合再把一次客户端请求扇出到 N 个后端调用并合并结果。如果任何一次聚合调用会超出时延预算,异步请求-回复就改返回轮询令牌,不再阻塞客户端。

  • 速率限制:在请求到达组合层之前就先拒掉多余的流量
  • 网关聚合:扇出再合并,让客户端只做一次往返
  • 异步请求-回复:对会阻塞太久的调用返回 202 + 令牌

遗留系统现代化

这三个——联合身份绞杀者无花果防腐层——构成「不搞大爆炸重写就能摆脱遗留单体」的经典集合。每个模式针对的都是一种独立风险:迁移之前先统一登录入口,然后是迁移路由器本身,最后是新旧契约之间的翻译。它们沿请求流分层,如下图所示:

模式针对的失败模式在请求流中的位置
联合身份每个子系统各自登录——每迁移一个就发明一套身份,登录体验碎成渣边界(边缘唯一的身份入口)
绞杀者无花果大爆炸重写风险——遗留系统仍在生产,新代码只能一片一片上路由器(按功能切流量)
防腐层遗留污染——新领域模型把老契约里的怪癖全吸进来翻译(遗留模型 → 新领域)
flowchart TB User[用户 / 客户端] User --> FID[联合身份<br/>统一身份边界<br/>SSO + 令牌交换] FID --> SF[绞杀者无花果<br/>按功能路由<br/>旧路径 vs 新路径] SF -->|已迁移功能| NewSvc[新微服务<br/>干净领域] SF -->|未迁移功能| Legacy[遗留系统] Legacy --> ACL[防腐层<br/>翻译遗留模型<br/>到新领域] ACL --> NewSvc style FID fill:#fff9c4 style SF fill:#c8e6c9 style ACL fill:#f8bbd0 style NewSvc fill:#e1f5ff style Legacy fill:#f5f5f5

从上往下读这张图:联合身份在边缘立起唯一身份边界,用户从旧到新切换子系统时不必再走一遍登录。绞杀者无花果按功能切流量——已迁移的路径直接进新服务;未迁移的仍走遗留,但先经过防腐层把遗留契约翻成新领域再交给新服务。新服务从来不直接讲遗留协议。

  • 联合身份:贯穿新旧系统的统一身份边界
  • 绞杀者无花果:按功能切流量,让迁移可以一步步推进
  • 防腐层:把遗留契约翻译成新领域模型

弹性分布式事务

这三个——发件箱Saga 模式断路器——构成「多服务事务在部分失败中存活下来、且不会丢事件」的经典集合。每个模式针对的都是一种独立灾害:本地原子写入、跨服务协调、每次步进的保护。它们沿时序流分层,如下图所示:

模式针对的失败模式在流程中的位置
发件箱双写异常——DB 已提交但事件没发出去(或反过来),状态与消息总线上不一致写入阶段(事件随本地 DB 提交原子落地)
Saga 模式跨服务不可能 ACID——多服务之间没有全局事务,部分失败会留下悬挂状态协调(前进步骤 + 语义反向)
断路器Saga 步进过载——慢参与者卡住编排器,整条后续链路停摆单步保护(封住每次调用的爆炸半径)
flowchart TB Tx[本地 DB 事务<br/>业务写入 +<br/>发件箱行追加] Tx --> Relay[发件箱中继<br/>轮询或日志尾随<br/>发到消息总线] Relay --> Bus[消息总线] Bus --> Orch[Saga 编排器] Orch --> CB{断路器<br/>关 / 半 / 开} CB -->|关| Step[Saga 步进调用<br/>到参与者服务] CB -->|开| FailFast[快速失败<br/>标记步骤可重试] Step --> SDb[(参与者数据库<br/>自身提交)] SDb -.发出下一步事件.-> Bus style Tx fill:#fff9c4 style Relay fill:#f8bbd0 style Orch fill:#c8e6c9 style CB fill:#e1f5ff

从上往下读这张图:本地 DB 事务把业务状态和发件箱行放在同一次原子提交里,状态与待发事件从此不再失同步;发件箱中继把发件箱行读出来发到消息总线;Saga 编排器消费这些事件,发出下一步,而每一步调用都被断路器守住,这样一个挂掉的参与者不会把整条 Saga 拖住。

  • 发件箱:保证事件与本地 DB 事务一起可靠发布
  • Saga 模式:用前向与补偿动作协调跨服务事务
  • 断路器:封住每次 Saga 步进的下游调用爆炸半径

模式选择标准

选择模式时考虑这些因素:

系统需求

📝功能需求

  • 可用性:可接受多少停机时间?
  • 性能:您的延迟需求是什么?
  • 可扩展性:您预期多少增长?
  • 一致性:您需要什么一致性保证?

技术限制

📝技术因素

  • 现有基础设施:已经有哪些系统?
  • 团队专业知识:您的团队了解哪些模式?
  • 技术栈:有哪些框架和库可用?
  • 预算:您可以分配哪些资源?

运营考量

📝运营

  • 监控:您能观察模式的行为吗?
  • 维护:持续维护有多复杂?
  • 测试:您能有效测试实现吗?
  • 文档:模式是否有良好的文档?

常见反模式

应用模式时避免这些常见错误:

⚠️模式误用

过度工程:不要将复杂的模式应用于简单的问题。从简单开始,根据需要添加模式。 模式堆叠:避免在没有明确理由的情况下组合太多模式。每个模式都会增加复杂性。 忽略权衡:每个模式都有成本。考虑性能开销、运营复杂性和维护负担。 货物崇拜实现:不要在不理解模式为何有效的情况下复制模式。根据您的特定情境调整模式。 有关代码级反模式(如上帝对象、货物崇拜编程和复制粘贴编程)的全面指南,请参阅软件开发反模式

入门指南

实现模式时遵循此方法:

1. 识别问题

清楚定义您试图解决的挑战:

  • 您遇到什么症状?
  • 根本原因是什么?
  • 您的成功标准是什么?

2. 研究模式

使用本指南识别候选模式:

  • 查看快速参考表
  • 遵循决策流程图
  • 阅读详细的模式文章

3. 评估选项

根据您的需求比较模式:

  • 实现复杂度
  • 运营开销
  • 团队专业知识
  • 预算限制

4. 从小处开始

从试点实现开始:

  • 选择非关键组件
  • 实现模式
  • 监控和测量结果
  • 根据学习进行迭代

5. 逐步扩展

扩展成功的实现:

  • 记录经验教训
  • 培训团队成员
  • 应用于其他组件
  • 根据经验改进

完整模式索引

以下是本系列涵盖的完整模式列表:

  1. 速率限制模式(一月)- 控制对限流服务的请求速率
  2. 防腐层模式(二月)- 保护架构免受遗留系统影响
  3. 重试模式(三月)- 优雅处理暂时性故障
  4. 提领检查模式(四月)- 减少消息负载大小
  5. 物化视图模式(五月)- 预先计算复杂查询
  6. 绞杀者无花果模式(六月)- 逐步迁移遗留系统
  7. 边车模式(七月)- 通过辅助组件新增功能
  8. 分片模式(八月)- 分散数据以提高可扩展性
  9. 网关聚合模式(九月)- 合并多个 API 调用
  10. 发布-订阅模式(十月)- 事件驱动通信
  11. 健康端点监控模式(十一月)- 主动健康检查
  12. 联合身份模式(十二月)- 集中化身份验证
  13. 断路器模式(一月)- 防止连锁故障
  14. 舱壁模式(三月)- 隔离资源以控制故障
  15. 异步请求-回复模式(四月)- 处理长时间运行的操作
  16. Saga 模式(七月)- 通过补偿机制编排跨服务的事务
  17. 补偿事务 - 撤销由一系列步骤共同完成的最终一致操作的工作
  18. 基于队列的负载均衡 - 在任务与服务之间以队列作为缓冲,平滑间歇性重负载
  19. 发件箱 - 将待发布消息存入本地事务的发件箱表,由独立进程可靠发布
  20. 缓存旁路 - 按需将数据从底层数据存储加载到缓存
  21. 索引表 - 为数据存储中查询频繁引用的字段创建二级索引
  22. CQRS - 分离读操作与写操作为不同模型以独立扩展
  23. 网关路由 - 通过单一端点将请求路由到多个服务之一
  24. 领导者选举 - 通过选举一个实例为领导者来协调分布式工作
  25. 外部配置存储 - 将配置信息移出应用程序部署包,集中存放到独立位置

其他资源

书籍

  • “Cloud Design Patterns” by Microsoft - 全面的模式目录
  • “Release It!” by Michael Nygard - 生产就绪软件模式
  • “Building Microservices” by Sam Newman - 微服务架构模式
  • “Domain-Driven Design” by Eric Evans - 战略设计模式

在线资源

实践

💡从实践中学习

学习模式的最佳方式是通过实践练习:

  • 构建实现每个模式的示例应用程序
  • 为使用这些模式的开源项目做出贡献
  • 与您的团队进行架构审查
  • 通过博客文章和演示分享知识

结论

架构模式是解决常见分布式系统挑战的强大工具。本快速参考指南帮助您:

  • 快速识别适合您问题的正确模式
  • 比较模式跨多个维度
  • 理解关系模式之间的关系
  • 避免常见陷阱在模式应用中
  • 规划您的学习通过模式目录的旅程 记住:模式是指南,不是僵化的规则。根据您的特定情境调整它们,测量它们的影响,并根据结果进行迭代。从简单的模式如重试和健康端点监控开始,然后随着系统的发展逐步采用更复杂的模式。

评论

请接受“功能性”Cookie 类别以查看和发表评论。