Architecture
架构的定义
简单来说,架构就是最高层的拆解与不可变的部分
- 如果我要搭建一个狗屋
- 不需要画图纸
- 不需要考虑地基
- 几块木板,几个钉子,几锤子下去,半天就能做好
- 歪了,踢一脚,踢坏了大不了重搭
- 如果我要建设一座城市
- 先规划:
- 功能分区:住宅区,商业区,工业区
- 基础设施:电网怎么走,管道如何铺设,交通网络的规划
- 地皮划分:每块地皮多大,楼能盖多高,楼与楼之间留多少空间
- 一旦道路修好,水管埋好,再变动这些就很难了
- 先规划:
修狗屋就是实现,规模小,影响小;建城市就是架构,做的是最高层的规划和设计,确定系统的骨架和规则
架构,就是决定系统长什么样、怎么成长以及各个部分如何配合的顶层设计
两个核心问题:架构要解决什么
任何架构设计,本质上都是在回答两个问题:
- 系统拆成几块
- 块之间如何通信
这两个核心问题可以进一步扩展为5个问题
- 系统由什么组成
- 数据存在哪里
- 逻辑写在哪里
- 模块间如何交互
- 数据如何流动
架构是系统的“骨架”和“蓝图”
一个软件里可能有多层级、多维度架构同时存在,同时叠加
软件架构的四个核心视角
- 结构视角(静态)
系统由哪些部分组成,例如
- 前端、后端、数据库
- 用户服务、订单服务、支付服务(微服务)
- 控制器、服务层、数据访问层(分层架构)
- 行为视角(动态)
各部分如何协作完成任务
用户下单 > 订单服务 > 库存服务 > 支付服务 > 通知服务
v v v v v
HTTP请求 创建订单 扣减库存 调用支付 发送邮件
- 技术视角(实现)
使用什么技术实现
- 决策视角(权衡)
为什么这样设计,权衡了什么
例如
- 使用微服务而不是单体:为了独立部署,但接受了分布式复杂度
- 使用缓存:提高性能,但要处理数据一致性问题
架构要解决的根本问题
五大核心关切
- 如何管理复杂度
- 分解:分而治之
- 抽象:隐藏细节
- 分层:关注点分离
- 如何应对变化
- 高内聚:相关功能放在一起
- 低耦合:减少组件间依赖
- 扩展点:预留演进空间
- 如何保证质量属性
- 可靠性:系统不出错或少出错
- 可扩展性:能否应对增长
- 可维护性:是否容易修改和调试
- 性能:响应时间和吞吐量
- 安全性:抵御攻击的能力
- 可用性:系统正常运行时间
- 如何协调团队协作
- 模块边界 = 团队职责边界
- 接口契约 = 团队协作协议
- 如何控制成本
- 技术选型成本
- 开发维护成本
- 运维部署成本
示例
一个完整架构描述
设计一个用户管理系统
# 1. 架构风格:清洁架构 + CQRS
风格:
- 六边形架构(端口适配器)
- CQRS(命令查询职责分离)
# 2. 组件划分
组件:
- 用户命令服务(处理创建、更新)
- 用户查询服务(处理查询)
- 认证服务
- API网关
# 3. 通信方式
通信:
- 命令侧:同步HTTP + 领域事件
- 查询侧:从读库直接查询
- 事件:Kafka消息队列
# 4. 关键技术决策
技术栈:
- 语言: Java + Spring Boot
- 数据库: PostgreSQL(写库) + Elasticsearch(读库)
- 缓存: Redis
- 部署: Docker + Kubernetes
# 5. 质量属性优先级
质量属性:
- 1. 安全性(用户数据敏感)
- 2. 可用性(99.9% SLA)
- 3. 可扩展性(支持千万用户)
- 4. 性能(查询响应<100ms)
# 6. 关键约束
约束:
- 必须符合GDPR数据隐私要求
- 现有团队熟悉Java生态
- 三个月内上线MVP版本
系统架构
决定:系统怎么拆、怎么部署、怎么通信
| 关注点 | 例子 |
|---|---|
| 服务拆分 | 单体/微服务 |
| 模块边界 | 微内核/插件 |
| 进程模型 | 主从/Actor |
| 部署形态 | Serverless |
应用架构
决定:业务逻辑如何组织
| 关注点 | 例子 |
|---|---|
| 依赖方向 | Clean/洋葱 |
| 分层方式 | 分层/六边形 |
| 用例组织 | DDD |
UI架构
决定:界面逻辑怎么解耦
| 关注点 | 例子 |
|---|---|
| UI解耦 | MVC/MVVM/MVP |
| 数据绑定 | 响应式架构 |
| 状态管理 | Redux/Flux |
领域架构
决定:业务模型怎么建
| 关注点 | 例子 |
|---|---|
| 领域拆分 | DDD分界上下文 |
| 规则表达 | 领域模型/充血模型 |
| 聚合根 | 实体/值对象 |
并发与调度架构
决定:系统如何跑
| 关注点 | 例子 |
|---|---|
| 并发模型 | Actor/事件循环 |
| 任务调度 | Job System |
| 实时系统 | 帧驱动/Tick |
数据架构
决定:数据怎么存、怎么流
| 关注点 | 例子 |
|---|---|
| 存储模式 | ORM/Repository |
| 数据流 | CQRS/Event Sourcing |
| 一致性 | 最终一致 |
插件&扩展架构
决定:系统是否可扩展
| 关注点 | 例子 |
|---|---|
| 模块化 | 微内核 |
| 插件加载 | 动态模块 |
| ABI边界 | C API/DLL |
软件风格架构(Architectural Styles)
分层架构(Layered Architecture)
┌─────────────────┐
│ 表现层/UI层 │ < 用户交互
├─────────────────┤
│ 业务逻辑层 │ < 核心业务规则
├─────────────────┤
│ 数据访问层 │ < 数据持久化
├─────────────────┤
│ 基础设施层 │ < 技术实现细节
└─────────────────┘
- 优点:关注点分离、易于理解
- 缺点:层间耦合、性能开销
- 适用:传统企业应用、CRUD应用
六边形架构(Hexagonal/Ports & Adapters)
┌─────────────────┐
│ 应用核心 │
│ ┌─────────┐ │
│ │ 领域模型│ │
│ └─────────┘ │
└────────┬────────┘
左侧适配器<端口>│<端口>右侧适配器
(输入) │ (输出)
┌──────┴──────┐ │ ┌──────┴──────┐
│ HTTP API │ │ │ 数据库驱动 │
│ 消息队列监听│ │ │ 外部API调用 │
│ CLI命令 │ │ │ 文件写入器 │
└─────────────┘ │ └─────────────┘
用户 │ 基础设施
- 核心思想:应用不依赖外部,外部通过适配器接入
- 适用:DDD应用、测试驱动开发