Software Architecture Evolution

软件架构风格核心定义

从单体到微服务、从管道过滤器到事件驱动,一图看懂软件架构的演进脉络与核心思想

架构风格核心定义

什么是「架构风格」?
组织 技术 约束 架构 风格 共同点 约束 可分析

「架构」= 一族约束的拓扑结构

每种风格都定义一套特定的元素类型和关系模式。就像建筑风格(哥特式 vs 现代主义)决定了建筑的形态与功能分区。

关键特征:它是一套命名系统,定义了参与者的角色与职责;是一套约束条件集合,限制了哪些连接是合法的;是一套语义规则,规定了数据如何流动。
  • 抽象层次:定义系统中各元素及其交互的抽象级别
  • 拓扑关系:规定组件之间的结构化排列方式
  • 约束条件:限制系统的可能行为空间
  • 可分析性:使系统能够被推理、验证和评估
  • 语义一致性:保证所有参与者对系统有相同的理解
  • 设计决策依据:为后续的设计选择提供指导框架
💡 一句话总结:架构风格就是关于如何组织代码和组件的一整套约定——它既是一种思维模型,也是一种设计语言,更是一套经过实践检验的最佳实践。

管道–过滤器风格

起源:Unix 管道 (1970s) | 典型代表:编译器、流式处理
核心思想

「数据在管道中逐级过滤变换」——每个处理单元(Filter)独立完成一个功能,通过管道(Pipe)将数据传递给下一个单元。

输出是前一个过滤器的输入,链式组合完成复杂处理任务。这是 Unix 哲学的精髓:cmd1 | cmd2 | cmd3

源数据
Source
过滤 A
Filter A
过滤 B
Filter B
结果
Output

典型应用场景:

  • 编译器前端:词法分析 → 语法分析 → 语义分析 → IR 生成
  • 流式数据处理:Kafka Streams / Flink 的 Pipeline 模式
  • 图像处理流水线:解码 → 滤波 → 增强 → 编码
  • HTTP 中间件链:Express/Koa 的中间件模式

✓ 优点

  • 松耦合,各 Filter 可独立开发测试
  • 支持增量处理,适合大数据流
  • 天然支持复用和重排组合
  • 易于理解数据流转过程

✗ 局限

  • 不适合需要共享状态的处理
  • 错误处理机制较复杂
  • 批量处理时效率受限
  • 难以表达复杂的控制流逻辑
🔑 适用场景:ETL 数据处理、日志分析、实时流计算、编译器设计、任何「输入→多步变换→输出」的场景。

分层架构风格

起源:OSI 七层模型 (1980s) | 经典模式:MVC / DDD
核心思想:「关注点分离」,每层各司其职

系统按职责划分为若干层,每层只依赖下层的服务,上层调用下层。这种严格的分层保证了系统的可维护性可替换性

只允许单向向下依赖——上层不知道下层的实现细节,只知道接口契约。

🎨 表现层 Presentation
↓ 调用 ↓
⚙️ 业务层 Business
↓ 调用 ↓
🧠 领域层 Domain (Core)
↓ 调用 ↓
💾 持久层 Persistence
↓ 调用 ↓
🔧 基础设施 Infrastructure
关键原则 — 依赖倒置:高层模块不应依赖低层模块,两者都应依赖抽象。
在实际工程中常使用 DI(依赖注入)IoC 容器 来实现这一目标。

常见分层变体:

  • MVC / MVP / MVVM:经典 UI 分层,View-Controller-Model 各司其职
  • 三层架构(3-Tier):表现层 + 业务逻辑层 + 数据访问层
  • DDD 四层架构:Interface → Application → Domain → Infrastructure
  • 六边形架构(Ports & Adapters):业务核心在外围适配器包围中
  • 洋葱架构(Onion):领域模型在最内层,层层包裹

✓ 优点

  • 职责清晰,新人容易上手理解
  • 某层可独立替换而不影响其他层
  • 便于团队分工协作(前端/后端/DBA)
  • 标准化程度高,工具生态成熟

✗ 局限

  • 层级过多会导致过度工程化
  • 变更需求可能穿透多层才能完成
  • 容易变成「反模式」(Anemic Model)
  • 单体部署,扩展性受限于整体
⚠️ 踩坑提醒:分层不是目的而是手段!不要为了分层而分层。很多项目的问题不是分得不够细,而是分得太死导致简单改动要改五六个文件。

事件驱动风格

起源:GUI 事件循环 (1990s) | 现代:EDA / CQRS / Event Sourcing
核心思想:「发布–订阅」解耦生产者与消费者

「发生了一件事,谁关心就通知谁」 —— 组件之间不直接互相调用,而是通过发送/接收事件消息来间接通信。

生产者只管发事件,消费者自己决定是否订阅。彻底解耦了调用者和被调用者之间的直接依赖。

Order
Service
发布事件
emit
📨 Event Bus /
Message Broker
Kafka / RabbitMQ
subscribe
Payment
Service
subscribe
Notification
Service
subscribe
Analytics
Service

相关概念体系:

  • Event Bus(事件总线):同一进程内的事件分发中心
  • Message Broker(消息代理):Kafka、RabbitMQ、RocketMQ 等
  • CQRS(命令查询职责分离):读操作和写操作分离,各自优化
  • Event Sourcing(事件溯源):状态变更以事件序列持久化而非快照
  • Saga 模式:分布式事务的补偿方案
  • Outbox Pattern:确保本地事务与消息发布的原子性

✓ 优点

  • 高度解耦,新增消费者无需改生产者
  • 天然异步,提升系统吞吐量
  • 支持削峰填谷(缓冲队列)
  • 便于构建弹性容错的分布式系统

✗ 局限

  • 最终一致性,不再有强事务保证
  • 调试困难,事件链路追踪复杂
  • 消息顺序和幂等性需自行处理
  • 引入额外的基础设施运维成本
🔄 常用消息队列对比:Kafka(高吞吐日志场景)| RabbitMQ(复杂路由)| RocketMQ(金融级可靠性)| Pulsar(云原生多租户)| Redis Stream(轻量级)

微服务架构风格

起源:2014 Martin Fowler | 代表:Netflix / Uber / 阿里
核心思想:「拆而治之」,独立部署的小型服务集群

「将单一应用程序划分成一组小的服务」,每个服务运行在自己的进程中,通过轻量级的 HTTP/gRPC 通信机制协同工作。

每个服务围绕特定业务能力构建,可独立开发、独立部署、独立扩展

🚪 API Gateway
路由 / 认证 / 限流
用户服务
User
订单服务
Order
商品服务
Product
支付服务
Payment
库存服务
Inventory

核心设计原则:

  • 单一职责:每个服务聚焦一个明确的业务边界
  • 自治性:团队拥有服务的完整生命周期(开发→部署→运维)
  • 去中心化:没有统一的数据库,每个服务有自己的数据存储
  • 故障隔离:一个服务挂掉不影响全局,通过熔断器保护
  • 基础设施自动化:CI/CD、容器化(Docker)、编排(K8s)
  • 可观测性:集中式日志、分布式追踪(Jaeger/Zipkin)、监控告警
🔥 热门微服务框架/平台:Spring Cloud(Java 全家桶)、Go-Micro / Go-Kit、gRPC + Protobuf、Service Mesh(Istio / Envoy)、Serverless(AWS Lambda / 函数计算)

微服务的代价(必须清醒认识):

  • 分布式复杂性:网络延迟、部分失败、数据一致性
  • 运维成本激增:几十个服务 = 几十倍的监控告警
  • 团队协作成本:跨服务接口契约管理、版本兼容
  • 性能开销:服务间网络调用比函数调用慢 100~1000 倍
  • 调试噩梦:一次请求跨越 5+ 个服务,链路排查极其痛苦

✓ 优点

  • 按需独立扩展高负载服务
  • 技术选型自由,不同服务可用不同语言
  • 故障隔离,单点故障不会雪崩全系统
  • 小团队敏捷迭代,缩短上市时间

✗ 局限

  • 分布式系统固有复杂性(CAP 定理)
  • 基础设施投入大(K8s、DevOps 团队)
  • 中小规模团队反而降低效率
  • 数据一致性保障难度大增
💡 何时该用微服务?团队 > 50 人、业务边界清晰、需要独立扩展、已有成熟的 DevOps 能力。否则先从模块化单体开始,别一上来就上 K8s。

C/S 与 B/S 架构风格

C/S: 1990s 客户端-服务器时代 | B/S: 2000s 浏览器普及时代
C/S 架构 — 客户端/服务器二阶模型

「客户端负责展示 + 部分逻辑,服务器负责数据存储和核心业务」。典型的胖客户端模式,客户端安装专用软件。

两层架构(2-Tier):客户端直连数据库服务器,后来发展为三层(3-Tier):Client → Application Server → Database Server。

C/S 变体:厚客户端(Rich Client 如桌面 App)| 薄客户端(Thin Client 如 X Window)| 移动端 Native App 本质也是 C/S
🌐 B/S 架构 — 浏览器/服务器三阶模型

「浏览器作为通用客户端,零安装即用」——B/S 是 C/S 的特殊形式,只不过客户端统一成了浏览器(Browser)。

Web 技术的成熟让 B/S 成为主流企业应用架构,免安装、跨平台、易更新是最大优势。

  • PWA / SPA:现代 Web 应用体验接近原生
  • 前后端分离:前端 Vue/React + 后端 RESTful API
  • SSR / SSG:Next.js / Nuxt.js 服务端渲染
  • BFF(Backend For Frontend):针对不同端定制的后端层
  • 无服务器(Serverless)/ WebAssembly:B/S 的下一代进化方向
C/S vs B/S 对比一览表
维度 C/S 架构 B/S 架构
客户端要求 需安装专用客户端程序 只需浏览器,零安装
用户体验 响应速度快,界面丰富流畅 依赖网络,体验略逊但差距缩小
开发维护 客户端需单独更新版本 服务端更新即可,客户端自动生效
跨平台能力 弱,需为各平台分别开发 强,浏览器天然跨平台
安全性 相对可控,可做更多本地安全策略 依赖 HTTPS/CORS 等Web安全机制
网络依赖 可离线工作(部分功能) 基本完全依赖网络
硬件资源 客户端承担较多计算压力 主要靠服务端算力
适用场景 专业工具、游戏、离线优先应用 企业管理系统、SaaS、信息门户
📌 趋势:界限正在模糊——Electron/Tauri 让 Web 技术写桌面 App(C/S 外壳+B/S 内核),PWA 让浏览器接近原生体验。未来是 「C/S 的能力 + B/S 的便捷」的融合方向。

📊 架构风格演进总览

架构风格 核心关键词 典型场景 复杂度
管道-过滤器 链式变换 / 流式处理 编译器、ETL、中间件 ⭐⭐ 低
分层架构 关注点分离 / 单向依赖 企业级 Web 应用、MVC ⭐⭐⭐ 中
事件驱动 发布订阅 / 异步解耦 消息队列、EDA、CQRS ⭐⭐⭐⭐ 较高
微服务 独立部署 / 分布式治理 大规模互联网平台 ⭐⭐⭐⭐⭐ 高
C/S & B/S 客户端-服务器 / 浏览器 桌面应用 / Web 应用 ⭐⭐ ~ ⭐⭐⭐⭐
🎯 架构选择的黄金法则:
没有最好的架构,只有最合适的架构。从简单开始,按需演进。大多数项目的起点应该是清晰的分层架构,当遇到真正的扩展瓶颈或组织痛点时,再考虑引入事件驱动或拆分微服务。

— 过度设计的系统比设计不足的系统更难维护。