软件架构特点及风格

1.软件架构解决的根本问题

软件架构 = 复杂性管理

核心矛盾:

矛盾 表现
复杂性 vs 可管理性 系统规模增长导致难以理解
可伸缩性 vs 性能 扩展能力与响应速度权衡
灵活性 vs 稳定性 变更能力与系统可靠性的平衡
可重用性 vs 特定需求 通用方案与定制功能的冲突

2.架构风格分类总览

按通信模式划分

分类 代表风格 核心思想
数据流 管道-过滤器、批处理 数据在组件间流动并被转换
调用 客户-服务器、RPC、REST 一方请求,另一方响应
事件 EBI、C2、消息队列 发布-订阅,异步通信
虚拟化 虚拟机、容器 隔离执行环境
移动代码 REV、COD、移动代理 代码作为数据元素移动
复制 复制仓库、缓存 数据多副本提高可用性

3.主要架构风格详解

3.1 管道-过滤器(Pipe and Filter)

解决的问题:

  • 数据处理流水线
  • 组件独立开发、测试、替换
  • 增量处理支持并行

示例:

1
2
3
4
# Unix管道是经典案例
grep "error" log.txt | sort | uniq -c
# ↓ ↓ ↓
# Filter Filter Filter
优点 缺点
组件高度可重用 不适合交互式处理
增量处理 性能随管道长度递减
易于维护 数据格式耦合

3.2 客户-服务器架构(Client-Server)

解决的问题:

  • 集中式资源管理
  • 安全边界控制
  • 负载均衡

变体演进:

变体 约束 解决的问题
CS 分离关注点 UI与逻辑分离
CSS +无状态 可伸缩性、故障恢复
C$SS +缓存 减少网络交互
LCS +分层 安全、中间件注入
RS 会话在服务器 简化客户端

无状态为什么重要:

  • 服务器无需保存会话 → 可随意增减实例
  • 故障恢复简单 → 重启即可继续
  • 负载均衡容易 → 请求可路由到任意服务器

3.3 事件驱动架构(Event-Based)

解决的问题:

  • 松耦合组件通信
  • 异步处理
  • 实时事件响应

架构示意:

Publisher A ──┐
              ├──→ Event Bus ──→ Subscriber B
Publisher C ──┘              ──→ Subscriber D

特点:

特性 说明
可扩展性 新增监听者不影响发布者
可进化性 组件替换不影响其他组件
缺点 难以调试、事件风暴风险

典型技术: RabbitMQ、Kafka、Node.js事件循环


3.4 移动代码架构

解决的问题:

  • 动态功能扩展
  • 平台无关性
  • 减少网络往返
风格 移动什么 执行位置 应用场景
VM 字节码 本地虚拟机 Java Applet、WebAssembly
REV 代码 → 远程执行 服务器 Webhooks、Serverless
COD 代码 → 本地执行 客户端 JavaScript、动态模块
MA 组件+状态+数据 远程站点 智能爬虫、网络代理

3.5 复制与缓存架构

解决的问题:

  • 单点故障容错
  • 就近访问降低延迟
  • 支持离线操作
复制仓库(RR):           缓存(Cache):
Client → Replica A ──┐    Client → [Cache] → Server
         Replica B ──┤         ↖_________↓
                     |────────── Hit:快速返回
                                  Miss:获取并缓存

缓存策略对比:

策略 一致性 性能 适用场景
写直达 金融系统
写回 最终 Web应用
TTL 时间窗 临时数据

3.6 分层架构

解决的问题:

  • 复杂性隔离
  • 关注点分离
  • 中间件能力注入

典型层次:

应用层    → HTTP、FTP、SMTP
传输层    → TCP、UDP
网络层    → IP
网络接口 → Ethernet、WiFi

代价: 每增加一层,增加延迟和处理开销


4.现代架构模式

4.1 微服务架构

解决的问题:

  • 单体应用复杂性
  • 团队规模扩展
  • 技术栈异构
  • 独立部署和扩展
┌──────────┐  ┌──────────┐  ┌──────────┐
│ Service  │  │ Service  │  │ Service  │
│   A      │  │   B      │  │   C      │
└────┬─────┘  └────┬─────┘  └────┬─────┘
     └─────────────┼─────────────┘
                   ↓
            ┌─────────────┐
                API网关     
            └─────────────┘

与REST的关系: 微服务通常遵循REST约束(无状态、统一接口、资源导向)


4.2 服务网格(Service Mesh)

解决的问题:

  • 服务间通信的横切关注点
  • 流量管理、熔断、限流
  • 可观测性(监控、日志、追踪)
  • 安全(mTLS)

机制: Sidecar代理模式,业务代码无需感知网络细节


4.3 事件溯源(Event Sourcing)

解决的问题:

  • 审计追踪
  • 时间旅行调试
  • 系统重组能力
Command → [Event Store] → Projections
                ↓
         不可变事件日志

4.4 CQRS(命令查询职责分离)

解决的问题:

  • 读写性能优化
  • 模型复杂度分离
  • 独立扩展

5.架构选择决策矩阵

根据问题域选择

问题特征 推荐架构 原因
数据处理流水线 管道-过滤器 模块化、可重用
集中式资源管理 客户-服务器 安全、控制
实时事件响应 事件驱动 松耦合、异步
跨组织协作 REST/HTTP 标准化、防火墙穿透
互联网规模 REST + CDN + 缓存 可伸缩
分布式一致性 复制仓库+共识算法 容错、可用
动态功能扩展 移动代码 灵活性

架构演进路径

单体架构
  ↓ 规模增长、团队扩展
模块化单体
  ↓ 部署频率、技术栈差异
微服务
  ↓ 网络延迟、一致性要求
服务网格 + 边车模式
  ↓ 基础设施复杂性
Serverless + 事件驱动

6.核心洞见

架构风格是一组协作的约束,通过施加这些约束来获得期望的架构属性。

  • 没有”最佳”架构,只有”最适合问题域”的架构
  • 架构决策应基于需求(功能+非功能),而非时尚
  • Internet规模的系统需要特殊考虑:无法控制的可伸缩性、独立部署、多信任边界