《软件架构基础》由 Mark Richards 和 Neal Ford 合著,是一本系统化介绍软件架构理论与实践的权威入门书。与许多偏重架构模式或特定技术的书籍不同,本书的核心贡献在于将软件架构工程化——提出了一套系统化的架构分析方法论,而非仅仅罗列设计模式。
两位作者都是软件架构领域的重量级人物。Mark Richards 是资深软件架构师,有超过 30 年的从业经验,在消息传递、微服务、事件驱动架构方面有独到的见解。Neal Ford 是 ThoughtWorks 的技术总监,也是知名技术会议的常客演讲者,对函数式编程、领域驱动设计和架构现代化有深刻理解。
市面上关于软件架构的书籍大致分为两类:一类偏向纯粹的理论和抽象原则(如《企业应用架构模式》),另一类偏向具体技术栈(如《微服务设计》)。《软件架构基础》的独特之处在于它架起了从原则到实践的桥梁:
作者给出一个非常务实且具有操作性的定义:
软件架构是对系统的结构(components)、组件之间的关系(connectors),以及受外部因素驱动的各种属性(architecture characteristics)所做的设计决策。这些决策在某种意义上至关重要,且难以在后期更改。
这个定义有三个关键维度:
这个定义的一个关键洞察在于:不是所有设计决策都是"架构决策"。只有那些难以更改的决策才属于架构范畴。比如,将某个 Controller 命名为 UserController 还是 CustomerController,虽然属于设计范畴,但很容易重构,因此不算架构决策。而选择使用 MySQL 还是 PostgreSQL、采用单体还是微服务、使用同步 RPC 还是异步消息,这些一旦实施就很难回头的决策,才是真正的架构决策。
作者将架构师的角色概括为四个方面:
| 角色维度 | 核心职责 | 关键能力 |
|---|---|---|
| 技术决策者 | 制定关键技术方向、选择技术栈 | 技术深度 + 广度 |
| 设计指导者 | 定义架构原则、模式和最佳实践 | 抽象思维 |
| 风险管理者 | 识别和缓解技术风险 | 风险识别与权衡 |
| 沟通协调者 | 与利益相关者有效沟通 | 技术写作、演讲、协商 |
书中提出了架构思维的四个层次,这也是区分优秀架构师和普通架构师的关键所在:
第一层:解决方案驱动思维
这是最常见的初始状态——看到需求就直接想到用什么技术来实现。比如"用户需要搜索功能 → 上 ElasticSearch"。这种思维的问题在于跳过了分析阶段,容易陷入"拿着锤子看什么都是钉子"的陷阱。实际上,搜索引擎架构本身就有很多维度需要考虑:数据量大小、索引更新频率、查询复杂度、一致性要求等,不能一上来就决定用某个特定工具。
第二层:问题驱动思维
先理解问题本质,再寻找合适的解决方案。比如"用户需要快速从海量数据中找到精确信息 → 是否需要全文搜索?是否需要模糊匹配?数据量有多大?对一致性要求如何?"——经过这些分析后,也许用 PostgreSQL 的全文索引就足够,根本不需要引入 ElasticSearch 这样的重量级方案。
第三层:权衡驱动思维
认识到任何架构决策都是权衡。没有完美的架构,只有适合的架构。比如选择微服务带来了独立部署和团队自治,但牺牲了运维复杂度和网络性能。能清晰表达每个决策的 trade-off 是一个架构师成熟的标志。在这个层次的架构师不会问"微服务好还是不好",而是问"基于我们当前的团队规模和业务复杂度,引入微服务带来的独立部署价值是否大于它引入的运维成本"。
第四层:演进驱动思维
架构不是一次性设计出来的,而是随着对业务理解的加深和外部环境的变化持续演进的。聪明的架构师会设计可以演进的架构,预留适应未来的回旋余地。具体来说,这包括:定义清晰的模块边界(方便后续拆分)、引入适配层(方便技术栈替换)、保持技术债可控(避免架构僵化)。
💡 个人经验:在实际工作中,大部分工程师停留在第一层,开始独立负责模块的工程师往往达到了第二层,而真正的架构师至少应该在第三层。第四层则是需要大量项目经验才能逐渐获得的。
架构特征是本书最核心的概念之一。它与传统上说的"非功能需求"(NFR)或 "-ilities" 基本等价,但作者将其系统化为一个可操作的分类框架。这是一个非常关键的贡献——绝大多数架构书籍要么把非功能需求当作附录一带而过,要么给出一个长长的列表却不知如何应用,而本书给出了切实可行的分析和评估方法。
一个关键的洞见是:有些架构特征是用户和业务方明确提出的(显性),但更多是隐性且极具破坏力的。
⚠️ 经验教训:不要只盯着业务方提出的功能需求。在项目早期就主动识别和明确隐性架构特征,否则到后期这些"欠的债"会十倍返还。实际操作中,我建议在需求分析阶段的最后专门安排一次"非功能需求研讨会",由架构师引导业务方和技术团队一起来梳理。
作者将常见的架构特征归纳为三类:
运行类(Operational)
| 特征 | 含义 | 常见指标 |
|---|---|---|
| 可用性(Availability) | 系统正常运行时间 | SLA/SLO 的 9 的个数(99.9% / 99.99%) |
| 连续性(Continuity) | 灾难恢复能力 | RTO(恢复时间目标), RPO(恢复点目标) |
| 性能(Performance) | 响应时间、吞吐量 | P50/P95/P99 延迟 |
| 可恢复性(Recoverability) | 故障后恢复能力 | MTTR(平均修复时间) |
| 可靠性(Reliability) | 系统无故障运行 | MTBF(平均无故障时间) |
| 鲁棒性(Robustness) | 异常输入的处理能力 | 错误处理覆盖率 |
| 可伸缩性(Scalability) | 处理能力随资源增加 | 水平/垂直扩缩效率 |
结构性(Structural)
| 特征 | 含义 |
|---|---|
| 可配置性(Configurability) | 运行时行为可调整 |
| 可扩展性(Extensibility) | 添加新功能的能力 |
| 可安装性(Installability) | 部署的简便性 |
| 可维护性(Maintainability) | 修改和理解代码的难易程度 |
| 可移植性(Portability) | 跨平台运行能力 |
| 可重用性(Reusability) | 组件可被复用到其他系统 |
跨领域(Cross-cutting)
| 特征 | 含义 |
|---|---|
| 可访问性(Accessibility) | 所有用户(含残障人士)可用 |
| 可归档性(Archivability) | 数据可长期保存和检索 |
| 身份认证(Authentication) | 用户身份验证 |
| 授权(Authorization) | 权限控制 |
| 合法性(Legal) | 合规性要求 |
| 隐私(Privacy) | 数据保护 |
| 安全性(Security) | 防攻击能力 |
| 可支持性(Supportability) | 运维支持 |
| 可用性(Usability) | 用户体验 |
作者提出一个极具实用性的方法:给每个架构特征打分,用 1-3 的量化标准来明确需求程度。
1 = 不需要特别设计(但仍有基础实现)
2 = 需要考虑(虽然不是核心关注点)
3 = 核心特征(必须重点设计)
示例:一个电商系统的架构特征评分
| 特征 | 评分 | 理由 |
|---|---|---|
| 可用性 | 3 | 核心业务,宕机 = 直接损失 |
| 伸缩性 | 3 | 大促流量波动巨大 |
| 安全性 | 3 | 涉及资金和用户隐私 |
| 可维护性 | 2 | 需要长期迭代,但可以接受一定技术债 |
| 性能 | 2 | 中等要求,秒级可接受 |
| 可配置性 | 1 | 优先用代码满足 |
| 可移植性 | 1 | 没有跨平台需求 |
评分的价值不在于精确性,而在于强迫团队对不同特征做显式的优先级排序。很多时候,团队对"什么最重要"其实并没有统一认识——业务方以为可用性最重要,架构师以为可维护性最重要,运维又以为性能最重要。通过评分过程,可以暴露并弥合这些认知差距。
在实际项目中,确定架构特征通常需要多轮沟通:
💡 个人经验:在一个跨境电商项目中,业务方说"必须支持全球用户访问"。但我们进一步追问后发现,前两年的策略就是服务好东南亚市场。如果当时不做区分直接在架构上支持"全球可用",就会引入不必要的复杂度——比如全球 CDN、多区域部署、数据本地化合规等。架构特征一定要和实际业务阶段匹配,做超前设计往往是浪费。
本书将架构风格系统化为一个有机的体系,从简单到复杂,从单体到分布式。这是全书篇幅最大、内容最丰富的部分,涵盖了八种主要的架构风格。
简单 ←—————————————————————————————————————————→ 复杂
单体分层 → 管道架构 → 微内核 → 服务化 → 事件驱动 → 微服务
(简单) (高复杂度)
这个光谱不是严格的分层,而是一个复杂度/灵活度的连续谱。左侧更简单、更可控,但灵活性和伸缩性有限;右侧灵活性更强,但代价是运维和开发复杂度。值得注意的是,不要默认选择右侧的风格——对于大多数系统来说,左侧的风格已经足够,引入多余的复杂度只会拖慢开发速度。
特点:
适用场景:
优势:
劣势:
⚠️ 常见陷阱:在单体架构中"微服务化"——即在单体内使用消息队列、远程调用来解耦,结果既没有单体架构的简单,也没有微服务的独立运维能力。在单体中保持简单的模块化就足够了,不要为了"可能以后要拆微服务"而让当前架构变复杂。
💡 个人经验:不要为"可能以后要拆微服务"而过度设计单体架构。我见过太多项目因为"以后可能搬"而在单体里做了复杂的领域隔离——每个模块有自己的数据库 schema 前缀、用了事件总线来做模块间通信——结果既增加了开发成本,最终也没拆。真正拆分时,你会发现大部分"提前设计"的东西都要重做。保持单体简单,拆分时再认真做。
管道架构(Pipeline Architecture)是最简单也最古老的架构风格之一,它的思想来源于 Unix 管道哲学——每个程序只做一件事,然后通过管道组合起来。
结构:
过滤器类型:
适用场景:
优势:简单、易理解、组件可复用性强
劣势:不适合复杂交互场景,管道间协调困难
微内核架构(Microkernel Architecture)也称插件架构(Plugin Architecture),是很多成熟软件的基础结构。
核心概念:
实际案例:
架构决策要点:
💡 个人经验:在某电商平台的规则引擎项目中,我们采用了微内核架构——核心规则引擎内置基础规则(如价格计算),复杂的促销规则通过插件注册。这样即使双 11 期间一次性注册上百条新规则,核心引擎也不受影响。不过要注意的是,插件 API 的设计非常关键,一旦发布就很难修改——插件接口的变更意味着所有插件开发者都需要跟着改,所以建议在第一个版本发布之前先做几轮实际插件的试用验证。
事件驱动架构(Event-Driven Architecture, EDA)通过事件的产生、检测、消费和反应来实现系统松耦合。这是构建大规模实时系统的首选风格之一。
两种拓扑结构:
1. 中介者拓扑(Mediator Topology)
使用一个中央事件中介者(Event Mediator)来协调多个事件处理步骤。
事件 → 事件中介者 → 处理链1 → 处理链2 → 处理链3
2. 代理者拓扑(Broker Topology)
没有中央协调者,事件在网络中自由流动,每个处理者独立响应。
事件 → 处理器A → 事件 → 处理器B → 事件 → 处理器C
↓
处理器D(独立消费)
事件类型:
| 类型 | 含义 | 举例 |
|---|---|---|
| 命令(Command) | 要求执行某个操作 | "创建订单" |
| 事件(Event) | 通知某个事情已发生 | "订单已创建" |
| 文档(Document) | 传递数据本身 | "订单详情文档" |
选择建议:对于简单的广播场景,使用代理者拓扑;对于需要编排的复杂业务流程(如订单履约),使用中介者拓扑。在大型系统中,往往两种拓扑共存。
微服务架构是当前最受关注但也最容易被误解的架构风格。作者在书中花了大量篇幅来澄清微服务的真正内涵和适用条件。
核心原则:
需要满足的条件(不是选择理由而是前提条件):
误区澄清:
❌ "微服务让开发更快"
✅ 微服务通常让开发更慢(多服务调试、跨服务事务、运维负担),它解决的是大规模团队的独立协作问题
❌ "微服务更适合小团队"
✅ 微服务需要成熟的 DevOps 和基础设施,小团队通常更适合从良好的单体开始
❌ "微服务 = 所有服务都尽可能小"
✅ 服务粒度的合理标准是"一个团队可以独立维护",而不是代码行数
❌ "微服务必须用消息队列通信"
✅ 通信方式取决于业务场景,简单的 CRUD 用 REST 就很好
微服务与分布式事务:这是微服务架构中最棘手的挑战之一。分布式事务的经典方案包括两阶段提交(2PC)、Saga 模式和 TCC(Try-Confirm/Cancel)。2PC 在微服务环境中通常不推荐(锁定资源时间长、协调者单点),Saga 模式是最常用的选择。Saga 有两种实现方式:事件编排(Choreography)和命令协调(Orchestration)。
作者提供了一个非常实用的决策框架:
1. 确定核心架构特征(3-5 个最高分)
2. 列出候选架构风格
3. 对每个候选风格评估它对每个特征的满足程度
4. 选择综合最优解
示例:一个互联网金融项目
| 架构特征 | 评分 | 单体 | 微服务 | 事件驱动 |
|---|---|---|---|---|
| 伸缩性 | 3 | 1 | 3 | 3 |
| 安全性 | 3 | 2 | 2 | 1 |
| 可用性 | 3 | 2 | 3 | 3 |
| 可维护性 | 2 | 2 | 3 | 2 |
| 简单性 | 1 | 3 | 1 | 1 |
| 总分 | 10 | 12 | 10 |
综合评分微服务胜出,但要注意的是评分只是辅助工具,最终决策还要考虑团队能力、时间线、组织架构等因素——一个仅有 5 人的团队,即使技术上微服务得分更高,从组织角度看也不是好选择。
每个架构决策都应该包含以下要素:
架构决策记录(Architecture Decision Record)是记录和沟通架构决策的重要工具。作者在书中极力推荐使用 ADR,这是团队架构治理中最重要的实践之一。
一个典型的 ADR 格式:
# ADR-001: 使用 PostgreSQL 作为主数据库
## 背景
需要为主业务系统选择数据库,数据模型复杂且需要强事务支持。
## 可选方案
1. PostgreSQL:开源关系数据库,支持事务和 JSON
2. MySQL:同样开源,但 JSON 和窗口函数支持较晚
3. MongoDB:文档数据库,但缺乏事务支持
## 决策
选择 PostgreSQL 13+
## 理由
- 需要复杂关联查询和事务支持(排除 MongoDB)
- PostgreSQL 的 JSONB 支持可以平滑应对部分半结构化数据
- 窗口函数和 CTE 查询比 MySQL 更成熟,性能更好
- 社区活跃,国内有成熟运维经验
## 折中
- 放弃了 MySQL 的大规模集群部署方案(Vitess)
- JSON 查询性能不如专门的文档数据库
- 运维团队需要额外的 PostgreSQL 培训
## 时间
2024-03-15
作者反复强调一个核心观点:架构的本质是权衡。没有一个架构决策只有好处没有代价。
常见的架构权衡:
| 你得到的 | 你失去的 |
|---|---|
| 高性能 | 一致性(最终一致性) |
| 高可用性 | 数据一致性(CAP 定理) |
| 松耦合 | 运维复杂度 |
| 独立部署 | 集成测试难度 |
| 灵活性 | 简单性 |
| 安全性 | 易用性 |
| 水平伸缩 | 运营开销 |
| 抽象层次 | 性能开销 |
💡 个人经验:我习惯为每个重要决策画一个"权衡矩阵"。比如在决定使用消息队列时,我会列出:获得了异步削峰能力,失去了请求响应的可预测性;获得了服务间的松耦合,失去了分布式事务的简单性。重要的是不要只说"选什么",要说清楚"放弃了什么"。如果一个架构决策无法清晰表达其放弃的价值,说明对这个决策的理解还不够深刻。
应对策略:
作者用 "T 型" 来描述架构师应该具备的知识结构:
深度
↑
┌───────────────┐
│ 一个深度 │
│ 技术领域 │
│ │
────┴───────────────┴──→ 广度
(对多种技术的了解)
作者的建议非常实用:
作者特别强调学习不同编程语言范式对架构思维的价值。每种语言范式都代表了一种独特的思维方式:
| 语言范式 | 代表语言 | 给架构师的启发 |
|---|---|---|
| 面向对象 | Java, C# | 封装、继承、多态,适合大规模协作 |
| 函数式 | Haskell, Scala, Clojure | 不可变数据、无副作用、组合式设计 |
| 面向切面 | AspectJ | 关注点分离、横切关注点 |
| 响应式 | Elixir, Erlang | 容错设计、"让它崩溃"哲学 |
| 系统级 | Rust, Go | 零成本抽象、并发模型、内存安全 |
作者提供了一个实用的判断标准:当你说出一个技术概念时,应该能够回答以下三个问题:
不需要成为每个技术的专家,但至少要能回答这三个问题。
架构师不能只画架构图,必须保持参与编码。作者对此有非常明确的表述:
Let me say it plainly: architects should code.
架构师保持编码的几个理由:
不过作者也强调,架构师不应花大部分时间写代码——理想的比例是每天花 20% 的时间在代码上,其余时间用于设计、审查、沟通和战略思考。比较理想的参与方式包括:做技术原型验证、解决最复杂的 bug、编写基础框架代码、参与代码审查。
| 陷阱 | 表现 | 后果 |
|---|---|---|
| 象牙塔架构师 | 只看架构图,不接触代码和实际业务 | 脱离实际,决策缺乏可行性 |
| 微观管理者 | 过度干涉实现细节 | 扼杀团队自主性,成为瓶颈 |
| 应试教育者 | 只会说教,不解决实际问题 | 失去威信,没人听 |
| 独裁者 | "我的架构不容质疑" | 团队不敢提意见,错失改进机会 |
| 万金油 | 什么都懂一点,什么都不深入 | 关键时刻给不出有分量的建议 |
技术设计评审:
知识传递:
培养后继者:
💡 个人经验:在我经历过的项目中,架构师和开发者的比例建议在 1:10 到 1:15。架构师太少,架构约束无法贯彻到代码层面;架构师太多,开发效率会严重下降。另外,我发现最有帮助的实践是**"架构师作为技术债务看护人"**——谁都可以引入技术债,但架构师要负责标记它、量化它、制定分期还债计划。不加管理的技术债才是毒药,被管理的技术债只是普通的工程技术决策。
架构治理是确保系统的实际实现与架构意图保持一致的过程。作者区分了架构治理与架构管理的差别:
简单来说,治理是制定游戏规则,管理是确保游戏按规则进行。
适应性治理 vs 命令式治理
| 治理方式 | 控制力度 | 典型工具 | 适用场景 |
|---|---|---|---|
| 命令式治理 | 强制 | Checkstyle, ESLint, 架构测试 | 必须严格遵守的规则 |
| 适应性治理 | 推荐 | 架构看板、原则文档、评审 | 需要灵活性的场景 |
实用的治理手段:
这是本书最有价值的原创概念之一。作者将架构适配函数定义为一组可编程的检查,用来持续验证系统是否满足架构约束。它的灵感来源于进化计算中的"适应度函数"概念——就像生物进化一样,系统应该通过持续检查来"进化",而不是靠死板的流程来"管控"。
示例:检查层间依赖
// ArchUnit 测试 - 检查 Controller 层只依赖 Service 层
@Test
public void controllersShouldOnlyDependOnServices() {
JavaClasses classes = new ClassFileImporter()
.importPackages("com.myapp");
ArchRule rule = layeredArchitecture()
.layer("Controller").definedBy("..controller..")
.layer("Service").definedBy("..service..")
.layer("Repository").definedBy("..repository..")
.whereLayer("Controller")
.mayOnlyBeAccessedByLayers("Controller");
rule.check(classes);
}
架构适配函数的分类:
| 类型 | 同步/异步 | 触发方式 | 示例 |
|---|---|---|---|
| 原子适配函数 | 同步 | CI 步骤 | 依赖检查、代码规范 |
| 整体适配函数 | 异步 | 定时执行 | 性能基准测试完整运行 |
| 持续适配函数 | 异步 | 生产环境 | 监控告警、日志分析 |
常见的适配函数场景:
《软件架构基础》是一本架构师系统化入门的最佳著作。它的最大价值不在于教了某个具体技术(微服务怎么做、消息队列怎么配),而在于给了你一套分析问题的思维框架。
具体来说,这本书让我印象最深刻的三个核心贡献:
| 侧重点 | 推荐书籍 | 理由 |
|---|---|---|
| 架构模式深入 | 《软件架构:架构模式、特征及实践指南》 | 同一作者(Neal Ford),深入讲解架构模式 |
| 架构师软技能 | 《软件架构实践》(第 4 版) | 涵盖更多架构师软技能和组织问题 |
| 分布式系统 | 《数据密集型应用系统设计》 | 分布式系统的深度分析,非常推荐 |
| 微服务 | 《微服务架构设计模式》 | 微服务模式的系统化讲解,作者 Chris Richardson |
| 架构决策 | 《恰如其分的软件架构》 | 风险驱动的架构决策方法 |
| 领域驱动设计 | 《领域驱动设计》 | Eric Evans 的原著,结合本书的微服务内容非常合适 |
读完本书后,你已经建立了完整的架构基础知识体系。下一步的进阶方向包括:
📚 读书笔记 | 架构师书架系列
本文是基于《软件架构基础》(Fundamentals of Software Architecture,作者 Mark Richards & Neal Ford)的读书笔记与系统化扩展。原书系统性强、可操作性高,适合作为架构师成长道路上的第一本系统读物。
相关读书笔记: