软件架构基础
每个系统都是从一块干干净净的白板开始的,而每一片让人头疼的遗留代码库,都曾经是某个人眼中的优雅构想。区别这两者的不是运气,而是架构。软件架构就是塑造系统如何成长的那一组决策,而这些决策会复利:第一个冲刺里做的一个选择,要么为你省下一年的重写,要么成为第二年不得不重写的元凶。这篇指南围绕"决策"而不是"图示"来组织。我不会给你一本教科书式的分类法,而是带你走一遍那些真正决定架构是优雅老去、还是变成工程师们悄悄避之不及的东西的选择点。如果你一心想直接冲进代码,建议先走 JavaScript 入门或 Web 开发的路子,把架构要坐在上面的原材料先攒起来。
架构师真正的工作是什么
架构是"在做实之前让取舍可见"的纪律。好的架构师不选"最好的"技术,他们选"团队的失败模式最能扛得住"的技术。这套取舍英文看得更清楚的,可以读我们的英文版系统设计基础。这意味着你要为"变化"而优化,不是为"完美"。每一个架构决策都是一场赌注,赌某些东西比别的更重要:赌流量会朝某个方向增长、赌团队会招某个技术栈的人、赌某家厂商会维持某个 API 的稳定。这份工作就是把赌注下得清醒,并把"你押了什么、为什么"写下来。想系统学这套在代码里落地决策的词汇,我们的软件测试基础和系统设计系列能给你打底。

耦合、内聚,以及真正要紧的边界
架构里有两大概念出大力,它们听起来很学术,直到某天救了你。高内聚指"本就属于一起的东西住在一起"——结账逻辑该和定价规则待在一起,而不是散落在整个工具类里。松耦合指系统各部分彼此依赖越少越好,改一处不会涟漪般波及十几处。当你设计服务、模块或层之间的边界时,你真正在决定的是"哪里改起来便宜、哪里改起来贵"。在变化速率不同的地方画边界——那就是架构该放一个清晰接口的接缝。

架构风格:一棵决策树
人们争论微服务还是单体,争得像是宗教问题,但它其实是一个"规模"问题。用一棵决策树,让约束来回答:

- 小团队、小产品、早期? 用模块化单体。部署简单、调试容易,将来可以在清晰的模块边界处拆分。
- 需要独立伸缩或有独立团队? 才考虑微服务,但只在边界稳定、且团队能端到端地拥有整条价值流时。
- 要求严格数据一致、低延迟? 优先用职权清晰的共享数据库,而不是分布式事务——后者实践起来非常痛苦。
- 事件驱动、高吞吐、生产者解耦? 在服务之间加 Kafka 或 SQS 这类消息代理,而不是同步调用。
- Serverless 契合流量和团队技能? AWS Lambda 或云函数很适合突发、无状态的负载,能大幅缩减运维面。
每一个都是交易,而错误的答案通常是"你的团队操作不起来"的那个。如果用这些还不够,数据分析和数据工程基础能帮你建立关于规模、队列和缓存的心智模型。
常见架构模式对比
下面是你真正会在它们之间做选择的模式的诚实对比,以及多数文章一笔带过的取舍:

| 模式 | 核心特点 | 成本 |
|---|---|---|
| 模块化单体 | 单一可部署、清晰的模块边界、运维最简单 | 无授权成本;花的是你自己的工程时间 |
| 微服务(Kubernetes) | 独立伸缩与部署、隔离、生态丰富 | 自建免费但运维沉重;托管 K8s 如 EKS 约 0.1 美元/小时/集群加节点 |
| 事件驱动(Apache Kafka) | 有序流、可重放、生产消费解耦 | 开源;Confluent Cloud 有免费档,之后按用量 |
| Serverless(AWS Lambda) | 按调用计费、免服务器管理、自动伸缩 | 免费档每月 100 万请求;之后约每百万请求 0.2 美元加计算 |
| 微前端 | 独立前端团队部署、规模化所有权 | 用你的前端技术栈即免费;真正的成本是共享工具链的复杂度 |
| 分层 / 整洁架构 | 依赖抽象、框架无关核心 | 无授权;成本是守住边界的纪律 |
模式不是"高级"的徽章。一个边界清晰的模块化单体,胜过一套"名义上是微服务、实则是分布式单体"的架构——后者是行业里最常见的失败模式。你操作不起来的复杂度就是负债,无论它的名字多潮。
数据层如何决定一切
架构师把大部分精力花在代码上,但数据层往往决定一个系统能否扛住现实的接触。决策是:你是事件溯源,真相来源是规范化的关系型存储,还是复制进一个读优化的数仓?分析流量走哪里才不会拖慢生产读?无论技术栈如何,你终究需要数据工程基础的纪律,别让分析负载腐化操作负载。给每张表定义清晰的归属边界、让迁移保持向后兼容、并尽早决定将来是否要分离 OLTP 与 OLAP,免得分析故事变成日后缠着你的事。

失败模式、测试与演进
架构是一种假设,生产就是你的实验。让假设可测:给每个关键依赖加健康检查、在慢的外部服务边界加熔断器、用对齐"业务结果"而非仅"CPU"的日志和指标让一切可观测。当某个边界被证明是错的,别等它硬化,趁早修。每季度做架构评审、把代码库指标放进 CI、并定一条明确的弃用策略,能让系统保持诚实。好的架构不是一次性的蓝图,它是一组在你脚下不断变化时仍守住边界的习惯——正是这些习惯,区分了能活十年的系统和两年就要重写的系统。
从架构到落地
把架构落地的最大误区,是把它当成"画图汇报"的行政工作。落地靠的是它和真实的工程实践咬合:带着取舍去评审、让边界可观测、把每次重大决策记进决策日志。更进一步,架构和你的数据库设计,以及把数据变成决策的分析能力是互相成就的——数据的形状往往就是架构的形状。
常见问题
什么时候是拆单体成微服务的正确时机?
当单一团队的瓶颈真实可见时——一次部署阻塞了无关的变更、一个团队无法独立伸缩、或一条热点路径逼你扩一些本不相干的模块。只在已经清晰的边界处拆,而且要增量地一次拆一个服务,绝不搞 big-bang 重写。
为什么我的微服务系统比原来的单体还慢?
因为每次网络调用都加延迟,而"分布式单体"会让一次请求做很多次同步往返。如果服务为了完成一次请求要串起一条长链互相调用,你就得到了两种世界的缺点。减少跳数、把逻辑往边缘推、能异步就异步,并且重新考虑那些服务是否真的该拆开。
关系型数据库和 NoSQL 该怎么选?
默认选关系型;它灵活、支持事务、普适性好。只有当你有具体理由时才选文档、键值或宽列存储:极高的写吞吐、真正灵活的文档形态、或你的关系型方案确实无法满足的水平扩展需求。用真实数据去重新评估,而不是被吹嘘带着跑。
两个人创业公司该用什么架构?
一个可部署的单体、一个数据库、清晰的模块布局。如果确能省钱,给几个明确隔离的任务加 Serverless 函数。别拿跑道去"买一门分布式系统课"。单体的那点温和限制,远比两人团队运维哪怕一个小 Kubernetes 集群要便宜。
正式的图示和架构文档有多重要?
有用,但常常做过头。真正重要的文档是记录决策及其理由的那些——"我们选了 A 而不是 B,因为 X"的笔记——它们能扛住团队人员流动。在每次重大选择处维护一份轻量决策日志,让代码本身成为主要的活文档,而不是一堆冻结的昂贵图示。想深入设计这笔账怎么算,可以看我们的数据库设计基础。