01 架构=要素+结构+连接
在软件行业,对于什么是“架构”一直众说纷纭,每个人都有不同的理解。不同书籍、不同作者的定义也未必统一。讨论架构之前,我们先明确概念——概念是认知世界和沟通的基础,如果对架构的理解不一致,沟通自然会遇到障碍。
Linux、MySQL、JVM都有架构,那使用Java开发、MySQL存储、运行在Linux上的业务系统,它的架构又是什么?要厘清这些问题,我们需要梳理几组相似又有关联的概念:系统与子系统、模块与组件、框架与架构。
1.1 系统与子系统
- 系统:泛指由一群有关联的个体组成,根据某种规则运作,能完成个别元件不能独立完成工作的群体。理解系统,需把握几个关键词:
- 关联:系统由有关联的个体组成。例如,单独的发动机和PC不能称为系统,但发动机、底盘、轮胎、车架组合起来就成了汽车。
- 规则:系统内的个体需按指定规则运作,规定分工与协作方式。例如,发动机产生动力,通过变速器、传动轴输出到车轮,驱动汽车前进。
- 能力:系统能力不是个体能力的简单相加,而是产生了新的能力。例如,汽车能载重前行,而它的各个部件本身并不具备此能力。
- 子系统:同样是由关联个体组成的系统,通常是更大系统的一部分。
1.2 模块与组件
它们都是系统的组成部分,只是从不同角度对系统进行拆分。模块是逻辑单元,组件是物理单元。
- 模块:从逻辑上分解系统,遵循“分而治之”原则,将复杂问题简单化。模块的粒度可大可小,可以是系统、子系统、服务、函数、类或功能块。划分模块的主要目的是职责分离。
- 组件:包括应用服务、数据库、网络、物理机,以及 MQ、容器、Nginx等技术组件。划分组件的主要目的是单元复用。英文“Component”对应中文“零件”,它具备“独立且可替换”的物理特性。如今,UI设计也越来越趋向组件化和模块化。
1.3 框架与架构
- 框架:通常指为实现某个业界标准或完成特定任务而制定的软件组件规范,也指为实现该规范所提供的基础功能软件产品。
- 框架是组件实现的规范,例如MVC、MVP、MVVM。
- 框架也是提供基础功能的产品,例如Spring、Django等开源框架,可以直接使用或二次开发。比如,SpringMVC是遵循MVC规范的开发框架,同时提供了注解、Spring Security、Spring JPA等诸多基础功能。
- 架构:关注的是结构。
框架与架构的区别显而易见:框架关注“规范”,架构关注“结构”。
在TOGAF9中,架构被定义为:一个系统的基本构件(子系统、模块、组件),体现在其构件、构件间的相互关系、构件与环境的关系,以及对系统设计和演进进行治理的原则中。
具体有两种含义:
- 一个系统的形式化描述,或指导系统实现的构件级详细计划。
- 一组构件的结构、构件间的相互关系,以及对构件的设计和随时间演进过程进行治理的原则与指导策略。
架构一词源于建筑。拆开看,“架”是将木头连接起来,“构”是结构。所以,“架构”就是把“木”按一定的结构连接起来。

对应到软件架构,“木”代表构件(要素),“结构”则是架构的产物。这里的“木”就是系统中的要素,我们称之为架构构件,可以是子系统、模块、应用服务或组件。结构是为解决不同场景而设计的产物。
连接,通过定义架构元素之间的接口、交互关系和集成机制来实现。连接可以是分布式调用、进程间调用或组件间的交互。
总结一下:架构的组成 = 要素 + 结构 + 连接,即将系统要素按特定结构进行连接交互。
基于以上,我们重新定义(见仁见智)软件架构:软件架构指软件系统的顶层结构设计。
架构是经过系统性思考,在现有资源约束下权衡利弊后的最合理决策,最终明确系统的骨架:包括子系统、模块、组件,以及它们之间的协作关系、约束规范和指导原则。它用以指导系统各方面的设计和统一团队的思想。
具体涉及四个方面:
- 系统性思考的合理决策:例如技术选型、实施方案(含执行计划)、成本与性价比评估。
- 结构:明确的系统骨架,即系统由哪些构件组成。
- 连接:系统的协作关系,即各部分如何协作实现业务请求。
- 规范:约束规范和指导原则,保证系统有序、高效、稳定运行,包括规范、原则、流程等。
02 没有架构设计?也许你的系统还不够复杂
如果没有架构设计,很可能说明你的系统还不够复杂。随着业务增长,系统会从单体应用逐步演化为分布式和微服务架构。
系统整体复杂性增加,技术团队可能从一个演变为多个专业化团队。此时若缺乏架构设计,系统将陷入无序和失控,带来诸多问题:
| 问题 |
原因 |
| 应用服务边界不清晰 |
拆分缺乏明确原则,为“微服务”而拆分,而非基于业务现状,导致系统无序、开发效率低。 |
| 应用服务层次不清,耦合严重 |
服务依赖形成网状结构,牵一发而动全身,后续修改与扩展困难。 |
| 系统应用服务跟踪困难 |
微服务化后逻辑复杂,服务出问题时难以快速定位和修复。 |
| 系统服务监控缺失 |
研发人员常缺乏监控意识,往往是问题发生后才考虑添加监控。 |
| 技术体系失控 |
不同团队使用不同技术栈或组件,导致公司内部技术架构失控,甚至为追求新技术而拿项目做试验。 |
当然,问题远不止这些。
架构设计的根本目的,正是为了解决系统复杂性带来的问题。其本质是对系统进行有序化重构,使之适应业务发展并具备快速扩展能力。
从架构的定义出发,其作用也体现在四方面:系统性思考的合理决策、明确的系统骨架、清晰的系统协作关系、以及约束规范和指导原则。
无论业务如何变化,架构师都需要理解业务、把控全局,权衡业务需求与技术实现。通过选择合适的技术解决关键问题,并指导研发落地,最终推动业务发展、提升效率。如果你在探索这些权衡与决策时,需要一个与同行交流的平台,可以到 云栈社区 看看。
03 此架构非彼架构?架构到底怎么分
在企业架构(EA)领域,RUP和TOGAF是两种常见的架构方法框架,它们也提供了架构分类的不同维度。
个人认为TOGAF的分类方式应用更广,这里简单展开。TOGAF9将架构分为以下几类:
| 架构类型 |
描述 |
| 业务架构 |
业务战略、治理、组织和关键业务流程。 |
| 数据架构 |
组织的逻辑和物理数据资产及数据管理资源的结构。 |
| 应用架构 |
描述被部署的单个应用系统、系统间交互及其与组织核心业务流程关系的蓝图。 |
| 技术架构 |
支持业务、数据和应用服务部署所必需的逻辑软硬件能力,包括IT基础设施、中间件、网络、通信、部署、标准等。 |
由于方法论不同,架构分类也有差异。RUP 4+1视图主要从架构生命周期视角描述,而TOGAF9则按架构涉及的内容维度来描述。
因此,我们可以结合两者,将架构细分为:业务架构、应用架构、数据架构、技术架构、代码架构、部署架构。
可以这样理解:业务架构是战略,应用架构是战术,技术架构是装备。 其中应用架构承上启下,既承接业务架构的落地,又影响技术选型。通常是:熟悉业务形成业务架构,根据业务架构制定应用架构,最后通过技术架构落地实施。

你也可以理解为:业务架构是生产力,应用架构是生产关系,技术架构是生产工具。 业务架构决定应用架构,应用架构需适配业务架构并随之进化,同时应用架构依托技术架构最终落地。
04 架构师都在说的单体应用、分布式与微服务到底是什么?

整体来看,架构的演进路径通常是:单体应用 -> 分布式应用服务化 -> 微服务。
下面我们来逐一解析。
4.1 单体应用
企业初期业务简单,可能只需支持某个简单场景的数据增删改查和基础逻辑,单体应用足以满足需求。
典型的三层架构:前端(Web/移动端)+ 中间业务逻辑层 + 数据库层。这是Java Spring MVC或Python Django等框架的典型应用模式。
针对单体应用的非功能性需求,通常做法有:
- 性能需求:使用缓存改善性能。
- 并发需求:使用集群改善并发。
- 读写分离:对数据库进行读写分离。
- 使用反向代理和CDN加速。
- 使用分布式文件和分布式数据库。
单体应用在初期易于部署和测试。然而,随着需求增长和团队扩张,代码库迅速膨胀,应用会变得臃肿,可维护性、灵活性下降,维护成本攀升。其主要缺点包括:复杂性高、技术债务积累、部署频率低、可靠性差、扩展能力受限,并可能阻碍技术创新。
4.2 分布式
为解决上述缺点,我们需要按业务功能模块拆分系统,将各模块服务化,转变为分布式系统。
业务模块部署在不同服务器上,通过接口进行数据交互。相对于单体架构,分布式架构提供了负载均衡能力,大幅提升了系统负载能力,能满足高并发需求。此外,它还有以下特点:
- 降低耦合度:模块拆分,使用接口通信,降低耦合。
- 责任清晰:项目拆分为多个子项目,不同团队负责不同部分。
- 扩展方便:增加功能时只需新增子项目,调用现有系统接口即可。
- 部署方便:可以灵活进行分布式部署。
- 提高代码复用性:例如,Service层采用分布式REST服务,可以被手机商城、微信商城、PC、iOS、Android等多端共用,避免了重复开发,易于统一维护升级。
- 缺点:系统间交互需远程通信,接口开发增加了工作量,但总体利大于弊。
4.3 微服务
当业务模式日益复杂,如订单、商品、库存、价格等模块逻辑深入(价格涉及会员等级、访问渠道、销售方式及大量促销规则),且规则复杂易冲突时,我们需要将分散在各业务的价格逻辑统一管理,以基础价格服务的形式透明供给上层应用,这就演变为微内核的服务化架构,即微服务。
微服务特点显著:易于开发维护、单个服务启动快、局部修改易部署、技术栈不受限制。
然而,微服务并非免费的午餐,它也带来诸多挑战:
- 运维要求高:更多服务意味着更多的运维投入。需要保证几十甚至上百个服务的正常运行与协作,挑战巨大。
- 分布式固有复杂性:微服务构建的是分布式系统,需面对系统容错、网络延迟、分布式事务等挑战。
- 接口调整成本高:微服务通过接口通信。修改某个服务的API,可能所有调用该接口的服务都需调整。
- 重复劳动:多个服务可能用到相同但未达到微服务拆分程度的功能,导致代码重复。虽然可用共享库解决,但在多语言环境下可能行不通。
05 15条普适的架构设计原则
掌握前人的经验,能让我们站在巨人的肩膀上。《架构真经》一书阐述了一些常用的架构原则。下面结合个人理解,分享15条具有普适价值的架构原则:
5.1 N+1设计
确保系统在发生故障时,至少有一个冗余的实例。
- 广泛应用于从数据中心到应用服务部署:发生故障时,系统至少有一个冗余实例。
- 必须确保:一个为自己,一个为客户,一个为失败。
5.2 回滚设计
确保系统可以向后兼容。
- 如果修复服务耗时很长,就要在限定时间内完成回滚。
- 灾难性事故(如损坏客户数据)可能在部署几天后才出现。
- 系统最好能通过发布或回滚来解决问题。
通过版本化实现回滚设计,一旦发生灾难性故障,可回滚到最近版本恢复服务。

5.3 禁用设计(功能开关、降级开关)
可以关闭任何发布的功能。
设计系统,特别是与其它系统或服务通信的高风险系统时,要确保能通过开关来禁用它们。这能为修复争取时间,并防止因错误需求导致系统宕机。

降级开关可通过配置中心(如Apollo)集中管理,利用推送机制将开关下发到各应用服务。
5.4 监控设计
在设计阶段就要考虑监控,而不是部署完成后才补。
- 通过监控发现系统可用性问题。
- 通过监控使系统自我诊断、自我修复成为可能。
- 通过监控确定系统预留空间的使用情况。
- 通过监控掌握系统间交互关系,发现瓶颈。

好的监控不仅能发现服务死活、检查日志,还能收集系统数据、评估终端用户响应时间。如果系统和应用在设计构建时就考虑监控,即使不能自我修复,至少可以实现自我诊断。
5.5 多活数据中心设计
- 数据是否全部集中在一个数据中心?
- 读写是否分离?
- 是否所有客户信息共享同一数据结构?
- 服务调用是否允许延时存在?
5.6 采用成熟的技术
工程师倾向于学习和实施时髦的新技术。新技术可能降低成本、缩短上市时间、提升性能,但也往往有更高的故障率。将新技术用于架构关键部分,可能严重影响可用性。
最好在多数人采用该技术时跟进,先将其用于对可用性要求不高的功能。待证明其能可靠处理日常交易后,再移植到关键任务领域。
5.7 故障隔离
避免单一业务占用全部资源,避免业务间相互影响。机房隔离避免单点故障。两个重要原则:
- 不共享原则:理想情况下,负载均衡、网络前端、应用服务器、数据库等,不共享任何服务、硬件和软件。
- 不跨区原则:不同隔离区之间无通信,所有服务调用必须发生在同一故障隔离区内。
5.8 水平扩展
水平扩展是指,随着业务发展需要扩大服务能力时,不必重构软件,通过增加设备即可满足需求。

- X轴扩展:服务器拆分。通过添加硬件设备扩容。
- Y轴扩展:数据库拆分。通过分解和部署服务扩容。
- Z轴扩展:功能拆分。按客户维度(如用户UID分表分库)分解部署以扩展容量。
5.9 非核心则购买
工程师常有自主研发所有系统的冲动。如果使用云服务,建议直接使用云厂商的相关产品,例如日志系统可以直接使用日志服务。
- 系统研发和维护都需要长期投入资源。
- 自研可能影响核心产品上市速度。
- 如果能形成差异化竞争优势,则自己做;否则,外购。
5.10 使用商品化硬件
在大多数情况下,便宜的就是最好的。标准、低成本、可互换、易于商品化是其特征。
如果架构设计得当,通过购买廉价服务器就能轻松实现水平扩展,前提是所有商品化硬件的总成本低于高端硬件的总成本。
5.11 快速迭代
这里有三个要点:
- 小构建:小构建成本低,能确保投资产生价值。
- 小发布:失败率与变更数量相关,小发布失败率低。
- 快试错:依据市场反馈快速迭代,加快产品上市时间,优化用户体验。

快速迭代需要完善的运维工具支持,如CMDB、持续集成工具、监控系统等。
5.12 异步设计
在同步系统中,个别子系统的故障会影响整个系统。常见两个现象:
- 同步系统中性能最慢的子系统,会成为整个系统的性能瓶颈。
- 同步系统中扩展性最差的子系统,会成为整个系统扩展的瓶颈。
5.13 无状态设计
- 无状态定义:应用服务运行的实例不会在本地存储需要持久化的数据,且多个实例对同一请求的响应结果完全一致。例如,单实例MySQL、ZooKeeper集群是有状态的,而单纯的Tomcat服务是无状态的。
无状态系统更利于扩展和做负载均衡。状态是系统吞吐量、易用性、可用性、性能和可扩展性的大敌,应尽量避免。
5.14 前瞻性设计
- Now:当前系统的架构、设计、能力、性能和扩展性。
- Now+1: 下一代预研系统的架构、设计、能力、性能和扩展性。
- Now+2: 下一代规划系统的架构、设计、能力、性能和扩展性。
5.15 自动化
设计和构建自动化的过程。如果机器能做,就不要依赖于人。人常犯错误,而且往往会以不同方式重复犯错。

06 6个架构设计的误区
最后,分享几个在架构设计实践中常见的误区,希望能带来一些启发。
- 开高走低,落不到实处。
- 遗漏关键约束与非功能需求。
- 为虚无的未来埋单而过度设计。
- 过早做出关键性决策。
- 客户说啥就是啥,成为传话筒。
- 埋头干活,缺乏前瞻性。
- 架构设计未考虑系统可测性。
- 架构设计企图一步到位。
误区1——架构专门由架构师来做,业务开发人员无需关注
架构再好,最终仍需代码落地。组织越大,落地难度越高。不单是系统架构,每个解决方案、每个项目也有自己的架构(如分层、设计模式)。如果每一块“砖瓦”不坚固,整个系统仍有崩塌风险,正所谓“千里之堤,溃于蚁穴”。
误区2——架构师确定了架构蓝图之后任务就结束了
架构不是“空中楼阁”,终须落地。如果架构师不深入一线,如何知道“地”在何处?又如何确保稳稳落地?
误区3——不做出完美的架构设计不开工
世上没有最好的架构,只有最合适的架构,不要企图一步到位。我们需要的是从单轮车 -> 自行车 -> 摩托车 -> 汽车的渐进过程。试想,一个需要两年才能造出的产品,当初的市场还可能存在吗?
误区4——为虚无的未来埋单而过度设计
创业初期,业务场景和需求边界难以把握,产品需要快速迭代和验证,需求频繁更新,此时首要任务是快速实现。不必过多考虑未来扩展,也许功能做完后效果不佳就被废弃了。当业务模式和应用场景边界已较清晰时,才应适当考虑未来的扩展性设计。
误区5——一味追随大公司的解决方案
大公司的成功光环效应,加上从大公司来的技术高手的影响,常使“XX就是这么搞的”成为最具说服力的论据。大公司的经验固然值得借鉴,但盲目追随会失去自我,在架构演化道路上迟早迷路。
误区6——为了技术而技术
技术是为业务服务的,脱离业务发展实际,一味追求时髦新技术,可能会将技术发展引入歧途,让架构之路越走越难。需要考虑实现成本、时间、人员等综合因素,在理想与现实之间找到平衡点。