写在前面
这是「后端架构实战」系列的第一篇。我写了不少 .NET、分布式、中间件、数据库的笔记,讲的都是"零件"。这个系列想聊的是另一件事:怎么把零件搭成一辆车——也就是软件架构。
但开篇我不想聊微服务、不聊 DDD、不聊任何具体风格。我想先回答一个更根本的问题:到底什么是"好架构"?
答案只有两个字:权衡。理解了这一点,后面七篇才有意义。
一、架构到底是什么
很多人对架构的印象是"画框图"——几张分层图、几个箭头、一堆方框。那是架构的产出,不是架构本身。
1
2
3
4
5
6
7
8
9
| 架构的本质:在约束下,做"职责如何分配"的决策
- 哪些东西放在一起,哪些东西拆开
- 哪些决策现在做,哪些决策推迟
- 哪些东西自研,哪些东西用别人的
- 哪些质量属性优先,哪些先牺牲
画图只是把这些决策记录下来。
没有决策依据的图,就是 PPT。
|
一个判断标准:如果你说不出"我为什么这么选、放弃了什么",那你就没在做架构,只是在抄。
二、第一性原理:一切都是权衡
Fred Brooks 有句名言:"没有银弹"(No Silver Bullet)——没有任何一种技术或方法能让软件工程的本质难题一夜消失。架构同理:
1
2
3
4
5
6
7
8
| 不存在"最好的架构",只存在"在当前约束下最合适的架构"
同一个系统,在不同团队、不同阶段、不同规模下,
"好架构"的答案完全不同。
10 人的电商团队和 1000 人的电商团队,
"正确"的架构天差地别——
不是谁对谁错,是约束变了。
|
所以资深架构师最常说的话不是"应该用 X",而是 “It depends”(看情况)。这不是圆滑,是因为架构决策永远依赖上下文。
三、约束的四象限
“It depends” 到底 depend 什么?四个维度:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| ┌─────────────────────────────────────────────────────────┐
│ 1. 规模(Scale) │
│ 用户量、数据量、QPS、团队人数 │
│ → 决定要不要拆、要不要分布式 │
│ │
│ 2. 时间(Time) │
│ 上市压力、迭代节奏、技术债务容忍度 │
│ → 决定先糙快还是先打好地基 │
│ │
│ 3. 团队(Team) │
│ 人数、技能栈、分布式经验、运维能力 │
│ → 决定能 hold 住多复杂的架构 │
│ │
│ 4. 成本(Cost) │
│ 服务器、人力、第三方服务、维护开销 │
│ → 决定自研还是采购、能上多少中间件 │
└─────────────────────────────────────────────────────────┘
四个维度互相牵制。规模涨了 → 团队要扩 → 成本要加 → 时间可能更紧。
架构决策 = 在这四个约束的"可行域"里找最优解。
|
关键认知:约束是会变的。今天的最优解,半年后可能就是技术债。所以架构不是一次定死,而是要能演进(第七节会展开)。
四、几个经典的权衡
4.1 性能 vs 可维护性
1
2
3
4
5
6
7
8
9
10
| 追求极致性能 → 紧凑的代码、手工优化、绕过抽象
✓ 跑得快
✗ 晦涩难懂、改一处崩三处、新人接手难
追求可维护性 → 清晰的抽象、分层、命名
✓ 好改、好懂、好测
✗ 多一层调用、多一点开销
绝大多数业务系统:优先可维护性(性能够用就行)
少数热路径(交易撮合、广告竞价):性能压倒一切
|
4.2 一致性 vs 可用性
这就是 CAP。分布式系统的所有痛苦都源于此:
1
2
3
4
5
| 要强一致 → 协调多数节点、锁、阻塞 → 牺牲可用性和性能
要高可用 → 允许暂时不一致 → 牺牲一致性,要处理冲突
详见我写的《分布式系统学习笔记(一):CAP 与一致性》。
本系列第五篇会讲它在数据层怎么落地。
|
4.3 简单 vs 灵活(最容易踩的坑)
1
2
3
4
5
6
7
8
9
| 过度设计(Over-engineering):
为"将来可能要用"的需求,提前搭了一堆抽象层
→ 现在用不上,将来真要用时发现猜错了
→ 维护成本白白增加
YAGNI 原则:You Aren't Gonna Need It。
不要为想象中的需求买单。
但也要留"可演进"的接缝——这不是矛盾,区别在于:
抽象 ≠ 灵活;接缝 ≠ 提前实现。
|
4.4 自研 vs 采购
1
2
3
4
5
6
7
8
9
10
| 自研:完全可控、贴合业务、无授权费
✗ 要投入人力、要自己维护、要踩坑
采购/开源:成熟、快、社区支持
✗ 黑盒、受制于人、可能有授权/合规问题
经验法则:
核心竞争力、差异化能力 → 自研
通用能力(消息队列、缓存、监控) → 用成熟方案
不要重新发明轮子,除非轮子是你的核心业务。
|
五、两大反模式
5.1 不设计(Cargo Cult 抄作业)
1
2
3
4
5
6
| "大厂都用微服务,我们也上微服务"
"别人用 K8s,我们也要 K8s"
→ 完全不看自己的规模、团队、问题
这是把"别人的解"套到"自己的题"上。
约束不同,照抄就是灾难。
|
5.2 过度设计(Resume Driven Development)
1
2
3
4
5
| "我想在简历上写 K8s + Service Mesh + 事件驱动 + CQRS"
→ 一个日活 100 的内部系统,上了全套云原生
简历好看了,系统难维护了,公司买单了。
技术选型的依据应是"问题",不是"我想学/想用"。
|
这两种病的共同点:决策没有回到约束和问题上。
六、架构是演进的,不是一次定死
1
2
3
4
5
6
7
8
9
10
11
12
| 架构的演进路径(也是本系列的主线):
单体 ──→ 模块化单体 ──→ 按领域拆分 ──→ 微服务 ──→ 云原生
每一步升级,都是在"旧架构扛不住新约束"时才发生:
单体扛不住团队规模 → 模块化
模块化扛不住并发 → 拆服务
服务多了扛不住运维 → 云原生
关键:
不要跳级。跳级 = 把未来的税提前交,还可能白交。
能用单体解决的问题,上微服务就是自找麻烦。
|
这也是为什么第二篇我要先为单体正名——大多数人低估了单体,高估了微服务。
七、怎么做一个架构决策
给一个可落地的决策框架:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| 1. 把问题讲清楚
不是"要不要上微服务",而是
"当前的痛点是什么?是发布耦合、扩容困难,还是团队协作?"
2. 列出所有候选方案
至少 3 个。哪怕第 3 个是"什么都不做"。
只有一个方案不叫决策,叫拍脑袋。
3. 对照四象限约束评估每个方案
规模 / 时间 / 团队 / 成本
列出每个方案的收益和代价(尤其是代价)。
4. 选定,并记录为什么放弃其他方案
这一步最重要。用 ADR(Architecture Decision Record)记下来:
- 背景、决策、理由、后果
半年后你会感谢自己。
5. 留好回滚 / 演进的接缝
决策可能是错的,约束会变。
确保架构能"进"也能"退"。
|
八、小结
- 架构 = 在约束下分配职责的决策,画图只是产出
- 没有银弹:不存在最好的架构,只有当前约束下最合适的
- 约束四象限:规模、时间、团队、成本——架构决策永远依赖上下文
- 四大经典权衡:性能↔可维护性、一致性↔可用性、简单↔灵活、自研↔采购
- 两大反模式:不设计(照抄)、过度设计(简历驱动)
- 架构是演进的:单体 → 模块化 → 拆服务 → 云原生,不要跳级
- 决策要记录:用 ADR 写清"为什么这么选、放弃了什么"
下一篇,我先替"单体"说句公道话——模块化单体才是大多数团队被低估的最佳实践。