构建具有韧性、可扩展的分布式系统需要针对特定挑战选择正确的架构模式。本指南提供快速参考,帮助您根据问题领域选择最合适的模式,并附上每个模式的详细说明链接。
模式选择快速参考
使用此表格快速识别哪个模式能解决您的特定挑战:
| 您的挑战 | 建议模式 | 使用时机 |
|---|---|---|
| 服务调用超时 | 异步请求-回复 | 操作时间超过 HTTP 超时限制 |
| 服务持续失败 | 断路器 | 防止不可用的服务造成连锁故障 |
| 暂时性网络故障 | 重试 | 处理快速恢复的暂时性故障 |
| 一个服务影响其他服务 | 舱壁 | 隔离资源以控制故障范围 |
| 跨服务业务事务 | Saga 模式 | 通过补偿机制编排跨服务的长时事务 |
| 需要撤销多步操作 | 补偿事务 | 通过语义反向操作回滚跨服务的部分工作 |
| 突发流量压垮服务 | 基于队列的负载均衡 | 在生产者和消费者之间以队列缓冲,平滑突发尖峰 |
| 本地写入 + 事件发布的原子性 | 发件箱 | 与本地数据库事务一起保证事件可靠发布 |
| API 限流错误 | 速率限制 | 控制对限流服务的请求速率 |
| 遗留系统集成 | 防腐层 | 保护干净架构免受遗留系统影响 |
| 查询性能缓慢 | 物化视图 | 预先计算复杂查询以加快读取速度 |
| 高频重复读取相同数据 | 缓存旁路 | 按需将数据加载到缓存以缓解读压力 |
| 需要按非主键字段快速查找 | 索引表 | 为查询频繁的字段建立二级索引 |
| 读写负载差异显著 | CQRS | 分离读模型与写模型以独立扩展 |
| 大型消息负载 | 提领检查 | 通过外部存储数据来减少消息大小 |
| 迁移遗留系统 | 绞杀者无花果 | 逐步用现代系统替换遗留系统 |
| 跨领域关注点 | 边车 | 在不修改应用程序的情况下新增功能 |
| 数据库可扩展性 | 分片 | 将数据分散到多个数据库 |
| 多个 API 调用 | 网关聚合 | 将多个后端调用合并为一个 |
| 多个服务版本或端点 | 网关路由 | 通过单一端点将请求路由到多个服务 |
| 事件分发 | 发布-订阅 | 解耦事件生产者与消费者 |
| 服务健康监控 | 健康端点监控 | 主动检测服务故障 |
| 需要单一协调者 | 领导者选举 | 通过选举一个实例为领导者来协调分布式工作 |
| 配置频繁变更 | 外部配置存储 | 在部署包外集中化管理配置 |
| 跨服务身份验证 | 联合身份 | 集中化身份验证和授权 |
模式分类
架构模式可以根据它们解决的问题进行分组:
🛡️ 韧性模式
帮助系统优雅处理故障的模式: 断路器:通过暂时阻止对失败服务的调用来防止连锁故障。就像电路断路器一样,当故障超过阈值时会”跳闸”,让系统快速失败并优雅恢复。 重试:自动重试失败的操作以处理暂时性故障。使用指数退避等策略来避免压垮已经承受压力的服务。 舱壁:将资源隔离到独立的池中,防止一个失败的组件消耗所有资源。以船舱命名,用于控制进水。 Saga 模式:通过正向操作和补偿操作,跨服务编排长时业务事务。与舱壁配套使用:舱壁隔离单个服务内部的故障;Saga 跨服务协调恢复。 [补偿事务]:撤销由一系列步骤共同完成的最终一致操作的工作。Saga 模式的基础:每个 Saga 步骤都需要在后续步骤失败时具备语义反向操作。 [基于队列的负载均衡]:在任务与它调用的服务之间引入队列作为缓冲,将任务与服务解耦。让消费者按自身节奏处理,平滑突发重负载,防止限流并提升可用性。 [发件箱]:在业务写入的同一本地事务中将待发布消息存入”发件箱”表,再由独立进程读取发件箱并发布到消息总线。解决当 Saga 事件必须与状态变更原子性发出时的双写问题。
组合韧性模式
这些模式最好一起使用:重试处理暂时性故障,断路器防止压垮失败的服务,舱壁控制故障的爆炸半径。Saga 模式在跨服务场景下与之互补——编排能够承受部分故障的多步事务。基于队列的负载均衡在脆弱依赖上游吸收突发流量,发件箱保证 Saga 事件与本地数据库事务可靠一同发布。
⚡ 性能模式
优化系统性能和响应性的模式: 异步请求-回复:将长时间运行的操作与即时响应解耦,防止超时并改善用户体验。 物化视图:预先计算并存储查询结果,避免在读取时进行昂贵的计算。适合复杂的聚合和报表。 [缓存旁路]:按需将数据从底层数据存储加载到缓存;应用程序优先从缓存读取,未命中则回退到数据存储并回填缓存。最常见的读侧优化——通常在考虑物化视图之前使用。 [索引表]:为数据存储中查询频繁引用、但主键未覆盖的字段创建二级索引。当查询模式具有选择性时,比物化视图更易于构建和维护。 [CQRS]:将读操作与写操作分离为不同的模型(往往使用不同存储)。读侧可独立于写侧扩展,读模型可以针对查询速度进行反规范化,代价是写侧的最终一致性。 提领检查:通过将大型数据存储在外部并仅传递引用来减少消息负载大小。改善消息系统性能并降低成本。 分片:将数据分散到多个数据库以提高可扩展性和性能。每个分片处理总数据的一个子集。
🔄 集成模式
促进系统间通信的模式: 防腐层:在具有不同语义的系统之间提供转换层,保护您的干净架构免受遗留系统怪癖的影响。 网关聚合:将多个后端服务调用合并为单一请求,减少客户端复杂性和网络开销。 [网关路由]:通过单一端点将请求路由到多个服务之一。与网关聚合和网关卸载自然搭配,共同构成完整的 API 网关。 发布-订阅:启用异步事件驱动通信,发布者不需要知道订阅者。 联合身份:将身份验证委派给外部身份提供者,实现跨多个系统的单点登录。
🎯 运营模式
改善系统运营和管理的模式: 速率限制:控制发送到服务的请求速率,避免限流错误并优化吞吐量。 健康端点监控:公开健康检查端点以进行主动监控和自动恢复。 边车:在应用程序旁部署辅助组件,处理日志记录、监控和配置等跨领域关注点。 [领导者选举]:从一组分布式任务实例中选举一个实例担任领导者,由其协调其他实例的工作。适用于需要一个单一协调者(例如调度或分片分配)但没有永久指定实例的场景。 [外部配置存储]:将配置信息从应用程序部署包中移出,集中存放到独立位置。让配置能够不重新部署即可变更,并支持环境特定值、特性开关和密钥。
🏗️ 迁移模式
支持系统现代化的模式: 绞杀者无花果:通过逐步将功能迁移到新实现来逐步替换遗留系统。以缠绕并最终替换宿主的无花果树命名。
决策流程图:选择正确的模式
使用此流程图导航到最适合您情况的模式:
模式比较矩阵
跨关键维度比较模式:
模式组合
许多实际系统结合多个模式以提供全面的解决方案:
韧性微服务堆栈
这四个——断路器、重试、舱壁、健康端点——是「每一次同步服务间调用都被它们包着」这套经典集合。每个模式针对的都是其它三个解决不了的失败模式,并按下图顺序分层:
| 模式 | 针对的失败模式 | 分层 |
|---|---|---|
| 健康端点 | 盲目运行——无法区分瞬时抖动和持续故障 | 检测(喂给其它三者) |
| 断路器 | 连锁故障——一个慢下游拖垮整张网 | 保护(调用前的闸门) |
| 重试 | 瞬时抖动——网络抖动、GC 暂停、短时过载 | 恢复(包住调用) |
| 舱壁 | 资源饥饿——一个吵闹邻居耗尽共享资源 | 隔离(每个下游的资源上限) |
从内往外读:舱壁给这个下游设了资源上限;断路器决定要不要继续;重试在闭合回路里处理每次调用的瞬时抖动;健康端点由监控轮询,喂给断路器状态机的信号。
- 断路器:防止连锁故障
- 重试:处理暂时性故障
- 舱壁:隔离资源
- 健康端点:启用监控
高性能 API 网关
这三个——速率限制、网关聚合与异步请求-回复——构成「高吞吐量公开 API 边缘」的经典集合。每个模式针对的都是其它两个解决不了的关注点:拒绝、组合还是时延缓解。它们沿请求流分层,如下图所示:
| 模式 | 针对的失败模式 | 在请求流中的位置 |
|---|---|---|
| 速率限制 | 后端过载——行为异常的客户端或突发流量打挂上游 | 入口闸门(先拒绝再做事) |
| 网关聚合 | 客户端来回过多——每次一屏要 N 次往返,移动端和弱网环境尤其痛苦 | 组合(扇出再合并) |
| 异步请求-回复 | 阻塞——一次慢下游调用就卡住线程并占住一条客户端连接 | 时延缓解(慢调用返回 202 + 轮询令牌) |
从上往下读这张图:速率限制是最外层闸门——先拒绝,绝不让恶意流量到达组合层;网关聚合再把一次客户端请求扇出到 N 个后端调用并合并结果。如果任何一次聚合调用会超出时延预算,异步请求-回复就改返回轮询令牌,不再阻塞客户端。
- 速率限制:在请求到达组合层之前就先拒掉多余的流量
- 网关聚合:扇出再合并,让客户端只做一次往返
- 异步请求-回复:对会阻塞太久的调用返回 202 + 令牌
遗留系统现代化
这三个——联合身份、绞杀者无花果与防腐层——构成「不搞大爆炸重写就能摆脱遗留单体」的经典集合。每个模式针对的都是一种独立风险:迁移之前先统一登录入口,然后是迁移路由器本身,最后是新旧契约之间的翻译。它们沿请求流分层,如下图所示:
| 模式 | 针对的失败模式 | 在请求流中的位置 |
|---|---|---|
| 联合身份 | 每个子系统各自登录——每迁移一个就发明一套身份,登录体验碎成渣 | 边界(边缘唯一的身份入口) |
| 绞杀者无花果 | 大爆炸重写风险——遗留系统仍在生产,新代码只能一片一片上 | 路由器(按功能切流量) |
| 防腐层 | 遗留污染——新领域模型把老契约里的怪癖全吸进来 | 翻译(遗留模型 → 新领域) |
从上往下读这张图:联合身份在边缘立起唯一身份边界,用户从旧到新切换子系统时不必再走一遍登录。绞杀者无花果按功能切流量——已迁移的路径直接进新服务;未迁移的仍走遗留,但先经过防腐层把遗留契约翻成新领域再交给新服务。新服务从来不直接讲遗留协议。
- 联合身份:贯穿新旧系统的统一身份边界
- 绞杀者无花果:按功能切流量,让迁移可以一步步推进
- 防腐层:把遗留契约翻译成新领域模型
弹性分布式事务
这三个——发件箱、Saga 模式与断路器——构成「多服务事务在部分失败中存活下来、且不会丢事件」的经典集合。每个模式针对的都是一种独立灾害:本地原子写入、跨服务协调、每次步进的保护。它们沿时序流分层,如下图所示:
| 模式 | 针对的失败模式 | 在流程中的位置 |
|---|---|---|
| 发件箱 | 双写异常——DB 已提交但事件没发出去(或反过来),状态与消息总线上不一致 | 写入阶段(事件随本地 DB 提交原子落地) |
| Saga 模式 | 跨服务不可能 ACID——多服务之间没有全局事务,部分失败会留下悬挂状态 | 协调(前进步骤 + 语义反向) |
| 断路器 | Saga 步进过载——慢参与者卡住编排器,整条后续链路停摆 | 单步保护(封住每次调用的爆炸半径) |
从上往下读这张图:本地 DB 事务把业务状态和发件箱行放在同一次原子提交里,状态与待发事件从此不再失同步;发件箱中继把发件箱行读出来发到消息总线;Saga 编排器消费这些事件,发出下一步,而每一步调用都被断路器守住,这样一个挂掉的参与者不会把整条 Saga 拖住。
- 发件箱:保证事件与本地 DB 事务一起可靠发布
- Saga 模式:用前向与补偿动作协调跨服务事务
- 断路器:封住每次 Saga 步进的下游调用爆炸半径
模式选择标准
选择模式时考虑这些因素:
系统需求
功能需求
- 可用性:可接受多少停机时间?
- 性能:您的延迟需求是什么?
- 可扩展性:您预期多少增长?
- 一致性:您需要什么一致性保证?
技术限制
技术因素
- 现有基础设施:已经有哪些系统?
- 团队专业知识:您的团队了解哪些模式?
- 技术栈:有哪些框架和库可用?
- 预算:您可以分配哪些资源?
运营考量
运营
- 监控:您能观察模式的行为吗?
- 维护:持续维护有多复杂?
- 测试:您能有效测试实现吗?
- 文档:模式是否有良好的文档?
常见反模式
应用模式时避免这些常见错误:
模式误用
过度工程:不要将复杂的模式应用于简单的问题。从简单开始,根据需要添加模式。 模式堆叠:避免在没有明确理由的情况下组合太多模式。每个模式都会增加复杂性。 忽略权衡:每个模式都有成本。考虑性能开销、运营复杂性和维护负担。 货物崇拜实现:不要在不理解模式为何有效的情况下复制模式。根据您的特定情境调整模式。 有关代码级反模式(如上帝对象、货物崇拜编程和复制粘贴编程)的全面指南,请参阅软件开发反模式。
入门指南
实现模式时遵循此方法:
1. 识别问题
清楚定义您试图解决的挑战:
- 您遇到什么症状?
- 根本原因是什么?
- 您的成功标准是什么?
2. 研究模式
使用本指南识别候选模式:
- 查看快速参考表
- 遵循决策流程图
- 阅读详细的模式文章
3. 评估选项
根据您的需求比较模式:
- 实现复杂度
- 运营开销
- 团队专业知识
- 预算限制
4. 从小处开始
从试点实现开始:
- 选择非关键组件
- 实现模式
- 监控和测量结果
- 根据学习进行迭代
5. 逐步扩展
扩展成功的实现:
- 记录经验教训
- 培训团队成员
- 应用于其他组件
- 根据经验改进
完整模式索引
以下是本系列涵盖的完整模式列表:
- 速率限制模式(一月)- 控制对限流服务的请求速率
- 防腐层模式(二月)- 保护架构免受遗留系统影响
- 重试模式(三月)- 优雅处理暂时性故障
- 提领检查模式(四月)- 减少消息负载大小
- 物化视图模式(五月)- 预先计算复杂查询
- 绞杀者无花果模式(六月)- 逐步迁移遗留系统
- 边车模式(七月)- 通过辅助组件新增功能
- 分片模式(八月)- 分散数据以提高可扩展性
- 网关聚合模式(九月)- 合并多个 API 调用
- 发布-订阅模式(十月)- 事件驱动通信
- 健康端点监控模式(十一月)- 主动健康检查
- 联合身份模式(十二月)- 集中化身份验证
- 断路器模式(一月)- 防止连锁故障
- 舱壁模式(三月)- 隔离资源以控制故障
- 异步请求-回复模式(四月)- 处理长时间运行的操作
- Saga 模式(七月)- 通过补偿机制编排跨服务的事务
- 补偿事务 - 撤销由一系列步骤共同完成的最终一致操作的工作
- 基于队列的负载均衡 - 在任务与服务之间以队列作为缓冲,平滑间歇性重负载
- 发件箱 - 将待发布消息存入本地事务的发件箱表,由独立进程可靠发布
- 缓存旁路 - 按需将数据从底层数据存储加载到缓存
- 索引表 - 为数据存储中查询频繁引用的字段创建二级索引
- CQRS - 分离读操作与写操作为不同模型以独立扩展
- 网关路由 - 通过单一端点将请求路由到多个服务之一
- 领导者选举 - 通过选举一个实例为领导者来协调分布式工作
- 外部配置存储 - 将配置信息移出应用程序部署包,集中存放到独立位置
其他资源
书籍
- “Cloud Design Patterns” by Microsoft - 全面的模式目录
- “Release It!” by Michael Nygard - 生产就绪软件模式
- “Building Microservices” by Sam Newman - 微服务架构模式
- “Domain-Driven Design” by Eric Evans - 战略设计模式
在线资源
实践
从实践中学习
学习模式的最佳方式是通过实践练习:
- 构建实现每个模式的示例应用程序
- 为使用这些模式的开源项目做出贡献
- 与您的团队进行架构审查
- 通过博客文章和演示分享知识
结论
架构模式是解决常见分布式系统挑战的强大工具。本快速参考指南帮助您:
- 快速识别适合您问题的正确模式
- 比较模式跨多个维度
- 理解关系模式之间的关系
- 避免常见陷阱在模式应用中
- 规划您的学习通过模式目录的旅程 记住:模式是指南,不是僵化的规则。根据您的特定情境调整它们,测量它们的影响,并根据结果进行迭代。从简单的模式如重试和健康端点监控开始,然后随着系统的发展逐步采用更复杂的模式。
评论
请接受“功能性”Cookie 类别以查看和发表评论。
评论加载失败。您可以重试,或前往 GitHub 查看讨论。
在 GitHub 上查看