架构模式
为什么要架构模式
- [软件设计](/软件工程/软件设计/软件设计.html) 的复杂性
架构模式的第一性分类轴
架构模式是对系统复杂性来源的不同应对方式。所有架构模式,均可投影到以下稳定维度上。
控制流主导权
- **调用驱动**:谁发起、谁控制执行顺序
- **数据驱动**:数据到达即触发处理
- **事件驱动**:状态变化驱动行为
数据与状态位置
- 状态是否集中
- 状态是否可共享
- 状态是否可重建
构件耦合方式
- 同步 / 异步
- 显式调用 / 隐式触发
- 时间耦合 / 空间耦合
演进与扩展方式
- 通过修改扩展
- 通过组合扩展
- 通过插件化扩展
风格与模式的关系
核心区分
| 层次 | 定义 | 粒度 | 典型示例 |
|---|---|---|---|
| 架构风格 | 系统的高层次组织方式 | 系统级 | 分层、微服务、事件驱动 |
| 架构模式 | 针对系统级反复出现问题的可复用解决方案 | 跨组件 | CQRS、Saga、API Gateway |
关系本质
架构模式 = 上下文(Context)+ 问题(Problem)+ 解决方案(Solution)架构风格 ≈ 解决方案的抽象结构
- **风格是模式的组成部分**:模式中的解决方案部分抽象到足够通用,即成为风格
- **模式是风格的具体化**:风格需要通过具体模式解决特定问题才能落地
架构风格
架构风格关注的是:系统整体组织方式,决定了系统的依赖拓扑与约束条件集,它限定了变更的影响范围、扩展的可能性边界、以及团队组织的协作模式
数据流风格
根本问题驱动
驱动问题:如何在高吞吐量场景下保持处理步骤的解耦?
历史脉络:早期批处理系统面临的问题——强耦合导致任何步骤变化都影响整体;Unix 管道哲学的启示——ls | grep | wc 的组合智慧;核心洞察——数据流动天然适合并行化,且步骤之间无需共享状态
根本矛盾:高吞吐量需求 vs. 处理步骤间的耦合成本
本质
- 以**数据流动**作为系统的主导力量
- 计算单元之间不共享状态
解决的根本问题
| 根本问题 | 本质 | 数据流风格的解法 |
|---|---|---|
| 提高吞吐量 | 需要并行化但不想引入复杂同步 | 数据流天然支持流水线并行 |
| 降低节点间的耦合 | 需要修改一个步骤不影响其他步骤 | 只通过数据交互,接口标准化 |
核心特征
节点间解耦:
- 数据只向前流动
- 节点职责单一
子模式
批处理
- 强时间顺序
- 强完整性校验
- 强流程控制
管道-过滤器
- 每个过滤器只关心输入与输出
- 管道负责数据传输
- 支持并行与复用
代价
数据流风格的本质约束:数据必须流经整个管道 ↓ 带来了两个不可避免的代价: 1. 因果链断裂 → 调试困难 2. 管道延迟累加 → 实时性差调用-返回风格
根本问题驱动
驱动问题:如何控制复杂系统的认知负担?
历史脉络:单体系统规模扩大后,缺乏结构化组织导致逻辑纠缠——所有逻辑纠缠在一起,无法理解、维护、修改;分而治之的思想起源——将大问题分解为可理解的小问题;核心洞察——层次化调用链使系统可被"逐层理解"
根本矛盾:系统的整体性 vs. 人类逐层理解的分段能力
本质
- 以**层次化调用链**为核心
- 调用方掌控执行顺序,被调用方同步返回结果
- 上层只依赖下层接口,不关心深层实现
解决的根本问题
- 分解复杂问题
- 通过层次化降低认知负担
典型形态
- 主程序 / 子程序(过程式)
- 面向对象调用
- 分层架构
代价
- 同步阻塞——调用方必须等待被调用方完成,实时响应能力受限
- 调用链延迟累加——深层调用链中,每层都有额外开销
- 远程调用成本高——跨进程/跨网络时代价显著
整洁架构
根本问题驱动
驱动问题:如何防止业务逻辑被技术细节绑架?
历史脉络:分层架构的困境——层间依赖方向混乱,业务逻辑依赖数据库/UI;核心洞察——依赖方向必须指向稳定,业务不应依赖易变的技术实现
根本矛盾:业务稳定性需求 vs. 技术实现的多变性
本质
同心圆结构,依赖方向指向内层。
+────────────────────────────────────────────────────────────────────+| Frameworks & Drivers || +------------------------------------------------------------+ || | Interface Adapters | || | +----------------------------------------------------+ | || | | Use Cases | | || | | +----------------------------------------+ | | || | | | | | | || | | | Entities | | | || | | | (Business Rules) | | | || | | | | | | || | | +----------------------------------------+ | | || | +----------------------------------------------------+ | || +------------------------------------------------------------+ |+────────────────────────────────────────────────────────────────────+ 依赖方向: 外层 ──────→ 内层 ↓ 依赖指向稳定核心原则
稳定内核,易变边缘:
- 内层不依赖外层
- 业务不依赖技术
- UI/DB 都是细节
价值
- 业务逻辑与技术实现分离
- 可独立演进
- 可测试性强
与分层架构的关系
整洁架构是分层架构的更严格形式——通过同心圆结构明确了依赖方向必须指向内层,避免逆向依赖。
微内核架构
根本问题驱动
驱动问题:如何让系统核心保持稳定,同时支持功能的差异化扩展?
历史脉络:操作系统内核设计的经验——最小化内核 + 插件扩展;核心诉求——产品线需求(同一核心 + 不同特性);核心洞察——变化的应被隔离,不变的应被固化
根本矛盾:核心稳定性需求 vs. 功能差异化扩展需求
本质
- **稳定核心 + 可变插件**
解决的根本问题
- 长期演进
- 功能差异化扩展
核心设计点
- 核心职责最小化
- 插件生命周期管理
- 插件通信机制
谦卑对象模式
将难测试部分隔离为简单的实现,让测试不依赖易变部分。是微内核架构实现可测试性的重要手段。
代价
- 架构设计难度高
- 插件边界难以划分
仓库风格
根本问题驱动
驱动问题:如何在多个构件需要共享数据时避免直接耦合?
历史脉络:直接调用的问题——构件间形成网状耦合;共享数据的启示——围绕数据组织而非调用链组织;核心洞察——中央数据存储作为协调点,构件通过数据间接通信
根本矛盾:数据共享需求 vs. 构件直接耦合的风险
本质
- 以**共享数据**为中心
- 构件通过共享数据协作
典型形式
- 数据库系统
- 超文本系统
- 黑板系统
代价
- 数据成为系统瓶颈
- 数据一致性复杂
架构模式
架构模式是在某一风格下,对特定问题的可复用解决方案。
事件驱动架构
根本问题驱动
驱动问题:如何在构件之间实现真正的时间解耦?
历史脉络:同步调用的困境——调用方必须等待被调用方完成;GUI 编程的启示——用户操作是事件,响应是事件处理器;核心洞察——状态变化是比调用更原语的事件
根本矛盾:时间解耦 vs 复杂性
本质
- 以**事件发布/订阅**为核心通信机制
- 发布者与订阅者在时间上完全解耦——发布者发出事件后不等待处理
- 构件之间通过事件消息间接通信
解决的根本问题
- 系统扩展性
- 构件解耦
核心特征
- 异步——处理不阻塞
- 隐式调用——发布者不知道订阅者
- 松耦合——构件可独立演进
两种组织方式
Mediator
有中心协调者
- 事件语义转换
- 业务流程编排
Broker
无中心协调者
- 纯消息路由
- 无业务逻辑
代价
- 调试与测试复杂
- 异常路径成本高
领域逻辑组织模式
决定了业务规则的结构化程度,直接影响系统对复杂度的抵抗能力和长期维护成本
关注:业务规则以什么形式存在。
事务脚本
事务脚本的隐含假设是:业务 = 操作序列
根本问题驱动
驱动问题:如何组织简单的业务逻辑?
历史脉络:简单业务场景——逻辑不复杂,不需要复杂的领域抽象;过程化编程的自然映射——一个请求 = 一个过程;核心洞察——复杂度不高时,最简单的结构就是最好的
适用条件:业务简单、生命周期短、逻辑无复用需求
本质
业务简单时,业务认知本身就是线性操作步骤,无需额外抽象
适用场景
- 业务简单
- 生命周期短
演进风险
- 复杂度指数增长
领域模型
根本问题驱动
驱动问题:如何用代码表达业务概念而非技术实现?
历史脉络:贫血模型的问题——业务逻辑散落在服务层,对象只是数据容器;面向对象应该同时包含数据和行为;核心洞察——领域模型是业务概念的软件映射
根本矛盾:业务表达清晰性需求 vs. 技术实现便捷性偏好
本质
领域模型是业务概念结构的同构映射——代码结构与业务结构一致。
核心价值
通过业务结构的同构映射,使业务复杂性可被结构化地分解和组织
代价
- **认知迁移成本**:从"技术实现思维"切换到"业务概念思维"是反人性的,需要刻意训练
- **模型维护成本**:模型随业务演化需要持续重构,多人协作时一致性维护成本高
- **人才稀缺性**:需要同时具备业务理解力 + 抽象设计力的团队成员
- **抽象泄漏风险**:任何模型都是简化,当复杂度穿透模型时需持续重构
表模块
表模块的隐含假设是:业务 = 数据的增删改查。与事务脚本模式一样,都属于过程式思维
本质
- 业务认知以数据库视角为主——业务逻辑天然映射到数据的 CRUD 操作
特点
- 强依赖数据库结构
- 适合数据密集型系统
服务层
本质
- 定义系统对外边界
- 协调领域对象
引入动机
- 多客户端复用
- 系统集成
架构演进路径与阶段矛盾
架构模式并非静态选择,而是随业务规模、技术环境、团队能力动态演进的产物。
各阶段核心矛盾与对应模式
架构演进背后是每阶段核心矛盾的转移:
| 阶段 | 核心矛盾 | 驱动的架构变化 |
|---|---|---|
| 单体 → 分层 | 认知负担 vs 业务复杂度 | 分层解耦 |
| 分层 → 模块化单体 | 部署效率 vs 扩展性需求 | 模块化边界 |
| 单体/分层 → 服务化 | 业务复用 vs 耦合成本 | SOA / ESB |
| 单体 → 微服务 | 迭代速度 vs 团队规模 | 按领域拆分 |
| 同步 → 事件驱动 | 响应实时性 vs 系统耦合 | 异步解耦 |
| 微服务 → 服务网格 | 治理复杂度 vs 业务聚焦 | Sidecar 代理 |
典型演进路径
路径一:单体到微服务(互联网路径)
单体架构 → 模块化单体 → 垂直拆分 → 核心域微服务化 → 完整微服务 → 服务网格触发条件:
- 团队规模不小
- 部署频率要求高
- 单体成为迭代瓶颈
核心原则:渐进式演进,避免全量重构
路径二:分层到整洁架构(企业路径)
分层架构 → 依赖倒置 → 领域分层 → 整洁架构 → 插件化扩展触发条件:
- 业务复杂度持续增长
- 技术实现频繁变动影响核心业务
- 需要支持多客户端复用
核心原则:依赖方向指向稳定,业务不依赖技术
路径三:事务到事件驱动(数据路径)
事务脚本 → 领域模型 → 事件溯源 → CQRS → 事件驱动触发条件:
- 读写性能分化明显
- 需要支持实时数据消费
- 复杂业务过程需要审计追踪
演进决策的判断标准
| 决策点 | 单体/分层 | 微服务 | 事件驱动 |
|---|---|---|---|
| 团队规模 | 小 | 中大型 | 任意规模 |
| 部署频率 | 月级 | 周/天级 | 持续 |
| 扩展需求 | 垂直扩展优先 | 水平扩展优先 | 弹性扩展 |
| 业务复杂度 | 中低 | 中高 | 高 |
| 一致性要求 | 强一致 | 弱一致 | 最终一致 |
| 团队能力要求 | 低 | 高 | 中高 |
演进决策框架
业务复杂度低 + 团队小 + 扩展需求低└──→ 分层架构(默认起点)业务复杂度高 + 需技术灵活性└──→ 整洁架构 / 六边形架构团队规模扩大 + 部署频繁└──→ 模块化单体(过渡态)扩展压力大 + 需独立部署└──→ 微服务架构高并发 + 需实时响应└──→ 事件驱动 / 空间架构核心稳定 + 需差异化扩展└──→ 微内核架构常见演进错误
| 错误 | 表现 | 后果 |
|---|---|---|
| 跳过中间态 | 直接从单体到微服务 | 分布式复杂度爆发 |
| 过度演进 | 小团队强上微服务 | 治理成本超过收益 |
| 进化不彻底 | 模块化单体但边界模糊 | 仍是单体困境 |
| 技术驱动演进 | 为技术趋势而改造 | 业务价值缺失 |
核心原则
- **渐进式演进优于革命性重构**:每次只跨一步
- **模式复杂度匹配问题复杂度**:不要超前设计
- **团队能力是演进上限**:选择团队能驾驭的下一个阶段
- **架构服务于业务价值**:演进目标而非技术纯粹性
架构设计不是选模式,而是管理复杂性来源。模式演进是对复杂性来源变化的回应。
反模式与常见误区
架构级反模式
大泥球
特征:系统缺乏可识别结构,模块边界模糊,相互缠绕。
后果:维护成本指数增长,系统脆弱,任何改动都可能引发意外故障。
根源:缺乏正式架构设计,开发者各自为政。
分布式单体
特征:将单体机械拆分为多个服务,但服务间高度耦合。
典型表现:所有服务使用同一套技术栈;服务间调用链过长;部署需要协调多个服务同时发布。
后果:继承分布式的复杂度,未获得分布式的收益。
过度分层
特征:层次过多,一个请求经过 5+ 层处理。
后果:延迟累加,追踪困难,增加不必要复杂度。
API 过度细分
特征:服务边界划出过细,一次业务操作需要客户端发起数十次调用。
后果:用户体验差,网络成为瓶颈。
决策级误区
| 误区 | 特征 | 后果 |
|---|---|---|
| 金锤思维 | 对所有问题套用同一种架构 | 忽视业务场景与团队能力匹配 |
| 过早优化 | 为想象中的扩展需求设计复杂架构 | 初期效率极低,团队被复杂度拖累 |
| 技术惯性 | 新建服务默认复用已有技术栈 | 失去技术多样性带来的灵活性 |
| 手段目标化 | 把"使用某种架构"本身当作目标 | 架构服务于技术趋势而非业务价值 |
反模式识别信号
| 信号 | 可能对应的反模式 |
|---|---|
| 无法回答"系统如何扩展" | 大泥球 |
| 改动一个服务影响多个服务 | 分布式单体 |
| 简单请求需要多次网络调用 | API 过度细分 |
| 无论场景都用同一种架构 | 金锤思维 |
| 小项目但架构很复杂 | 过早优化 |
关联内容(自动生成)
- [/软件工程/架构/架构.html](/软件工程/架构/架构.html) 架构模式是软件架构设计的具体实现方式,与整体架构理念和原则密切相关
- [/软件工程/架构模式/分层架构.html](/软件工程/架构模式/分层架构.html) 分层架构是架构模式中最基础和常见的模式之一,与本文档中提到的架构风格和模式有直接关联
- [/软件工程/设计模式/设计模式.html](/软件工程/设计模式/设计模式.html) 设计模式与架构模式在系统设计中有密切联系,设计模式是架构模式在更细粒度上的实现
- [/软件工程/微服务/微服务.html](/软件工程/微服务/微服务.html) 微服务架构是现代架构模式的重要发展方向,体现了本文档中提到的构件解耦和扩展性原则
- [/软件工程/架构模式/响应式架构.html](/软件工程/架构模式/响应式架构.html) 响应式架构是事件驱动架构的延伸和发展,体现了现代系统对高可用性和弹性的要求
- [/软件工程/架构/系统设计/架构设计.html](/软件工程/架构/系统设计/架构设计.html) 系统架构设计是架构模式的实际应用场景,将理论模式转化为具体的设计方案
- [/软件工程/架构模式/Web框架.html](/软件工程/架构模式/Web框架.html) Web框架是架构模式在Web开发中的具体体现,展示了如何将架构模式应用于特定领域
- [/软件工程/架构/系统设计/分布式/分布式系统.html](/软件工程/架构/系统设计/分布式/分布式系统.html) 分布式系统设计中广泛应用了本文档提到的各种架构模式,特别是事件驱动和分层架构
- [/软件工程/架构/架构治理.html](/软件工程/架构/架构治理.html) 架构治理确保架构模式在实际项目中的正确实施和持续演进
- [/软件工程/领域驱动设计.html](/软件工程/领域驱动设计.html) DDD与架构模式密切相关,特别是在领域逻辑组织模式方面,两者相辅相成
- [/软件工程/软件工程.html](/软件工程/软件工程.html) 架构模式存在的根本原因是软件工程复杂性的控制需求,软件工程是架构模式的理论根基
- [/软件工程/DevOps.html](/软件工程/DevOps.html) 架构演进与DevOps持续交付理念高度关联,演进式架构是DevOps文化的技术支撑
- [/软件工程/架构模式/基本模式.html](/软件工程/架构模式/基本模式.html) 基本模式是架构模式的细粒度组成部分,提供边界控制、对象抽象、替换性等微观结构能力
- [/软件工程/架构模式/表现层.html](/软件工程/架构模式/表现层.html) MVC/MVP/MVVM是表现层内部职责分离的子模式,属于架构模式在用户交互层的具体实现
- [/软件工程/架构模式/对象关系模式.html](/软件工程/架构模式/对象关系模式.html) 对象关系模式处理领域模型与数据存储的结构映射,与仓库风格等架构模式密切相关