夜雨聆风学习资料网

ARTICLE · 1086632

第16讲:软件架构设计

第16讲:软件架构设计
软件架构(Software Architecture)是软件系统的整体组织结构以及影响系统结构和质量的关键设计决策。它关注系统由哪些主要部分组成、这些部分之间如何协作,以及为什么采用这样的组织方式。
软件架构设计处于需求分析和详细设计之间,是连接业务需求与软件实现的重要桥梁:业务需求分析→ 软件架构设计 → 详细设计 → 编码实现。架构设计并不只是绘制一张架构图,而是围绕系统目标,对系统结构、组件关系、接口、数据、部署方式以及关键技术决策进行设计,并重点解决性能、可用性、安全性、可维护性、可扩展性等质量属性问题。
1  软件架构设计相关概念
1.1 软件架构的作用
软件架构主要具有以下作用:
  • 管理复杂性:通过系统分解、模块化和明确边界降低系统复杂度。
  • 保证系统质量:通过架构设计支持性能、可用性、安全性、可维护性和可扩展性等质量属性。
  • 指导软件开发:为模块划分、接口设计、数据设计和部署提供总体约束。
  • 控制技术风险:在系统实现之前识别关键技术风险,并通过原型、评审和测试进行验证。
  • 支持系统演进:通过合理的模块和服务边界,使系统能够适应未来需求和技术变化。
因此,架构设计的核心不是选择“最先进的技术”,而是根据系统目标和约束进行合理的设计与权衡(trade-off)。
1.2 架构设计与详细设计
软件架构设计和详细设计关注的抽象层次不同。架构设计主要回答:系统由哪些主要部分组成?它们如何协作?如何满足关键质量属性?详细设计主要回答:每个部分具体如何实现?
例如,一个订单系统在架构层面可以确定:用户→ 订单服务 → 支付服务→ 消息系统→ 库存服务。而详细设计则进一步确定订单服务中的类、接口、算法、数据库表和具体代码。
因此,可以简单理解为:

层次

主要问题

需求分析

系统需要解决什么问题?

架构设计

系统整体如何组织?

详细设计

各部分具体如何实现?

编码

如何将设计实现为程序?

需要注意,架构和详细设计并不是完全割裂的。详细设计过程中发现的问题可能反过来促使架构调整,因此现代软件开发中的架构是一个持续演进的设计过程。
1.3 利益相关者与架构关注点
软件系统通常存在多个利益相关者(Stakeholder),例如,用户、产品经理、开发人员、测试人员、运维人员和安全人员。不同利益相关者关注的问题不同。
  • 用户关注: 易用性、性能、可用性,
  • 开发人员关注: 可维护性、可测试性,
  • 运维人员关注: 可部署性、可观测性、可靠性,
  • 安全人员关注: 身份认证、授权、数据安全,
  • 管理人员 关注: 成本、进度、风险。
因此,架构设计首先需要识别利益相关者及其架构关注点(Architecture Concerns),再将这些关注点转化为架构需求和设计决策。这也是为什么复杂系统通常需要通过不同的架构视图来描述,例如:
  • 模块视图:系统由哪些模块组成;
  • 运行时视图:模块运行时如何交互;
  • 部署视图:软件如何部署到服务器、容器或云平台。
1.4 架构师的职责
架构师的主要职责不是“画架构图”,而是解决系统层面的关键设计问题并做出架构决策。主要包括:
  • 理解业务目标、需求和约束;
  • 识别影响架构的关键需求和质量属性;
  • 设计系统结构、模块边界和主要交互方式;
  • 选择合适的架构风格、技术和架构策略;
  • 分析不同方案的成本、收益和风险;
  • 通过架构评审、原型和测试验证关键设计;
  • 与开发、测试、运维等团队沟通并维护架构;
随着业务和技术变化持续演进系统架构。因此,可以将软件架构设计概括为:从业务目标和需求出发,识别架构驱动因素,设计系统结构并进行关键技术决策,在各种质量属性和工程约束之间进行权衡,并通过验证和持续演进保证系统的长期质量。
这一认识也构成后续学习架构模式、质量属性、架构视图、云原生架构以及人工智能软件架构的基础。
2 架构驱动因素与质量属性
软件架构不是凭空产生的,而是由系统的业务目标、功能需求、质量要求以及各种约束共同驱动的。其中,架构驱动因素(Architectural Drivers)是对架构设计具有重要影响的需求和约束,而质量属性(Quality Attributes)则描述系统应该具有什么样的特性。
因此,架构设计可以概括为:业务目标→需求与约束→架构驱动因素→架构决策→系统结构。
2.1 架构驱动因素
架构驱动因素是影响系统总体架构的重要因素,通常包括:
  • 业务目标:系统需要创造什么业务价值;
  • 功能需求:系统需要提供哪些主要功能;
  • 质量属性:系统需要达到怎样的性能、可靠性、安全性等;
  • 技术约束:已有技术平台、编程语言、数据库或基础设施;
  • 组织约束:团队规模、人员技能和开发方式;
  • 法规与标准:数据保护、行业规范和合规要求;
  • 成本与进度:项目预算、交付时间等。
并不是所有需求都具有相同的架构影响。架构设计应重点识别那些会显著影响系统结构或技术决策的需求。例如,“系统支持用户修改昵称”通常不会对总体架构产生重大影响;而“系统需要支持百万级并发用户”则可能直接影响服务划分、缓存、数据库、部署和扩展策略,因此属于重要的架构驱动因素。
2.2 功能需求与架构
功能需求描述系统需要做什么,例如:用户注册和登录;商品查询;创建订单;在线支付;生成报表。功能需求通常决定系统需要提供哪些主要功能模块。例如,一个电商系统可以形成:用户→商品管理→购物车→订单→支付→物流。但是,仅根据功能需求通常还不能确定完整的架构。例如,同样是“在线支付系统”,如果要求:支持每天数千万次交易,并且支付服务全年保持高可用。这些是架构设计的重要依据。但必须进一步考虑:高并发、数据一致性、故障恢复、安全等等。
因此,功能需求决定系统“做什么”,质量属性和约束则很大程度上决定系统“应该怎样做”。
2.3 质量属性
质量属性描述系统除功能之外的重要特征,是架构设计的重要依据。常见的质量属性包括:

质量属性

关注的问题

性能(Performance)

系统响应多快、处理能力多强

可用性(Availability)

系统能够持续提供服务的能力

可靠性(Reliability)

系统在规定条件下正确运行的能力

安全性(Security)

防止未授权访问和数据泄露

可维护性(Maintainability)

修改和维护系统的难易程度

可扩展性(Scalability)

系统应对负载增长的能力

可测试性(Testability)

验证系统行为的难易程度

可部署性(Deployability)

软件发布和部署的难易程度

不同质量属性往往需要不同的架构策略。例如:高性能意味着需要考虑缓存、并发、异步处理;高可用需要考虑冗余、故障转移、数据复制;高安全需要考虑认证、授权、加密、审计;高可维护性需要关注模块化、低耦合、清晰接口。
需要注意的是,质量属性通常不能通过一个简单的功能测试来判断,而需要转化为可度量、可验证的目标。
2.4 质量属性场景(Quality Attribute Scenario)
质量属性场景(Quality Attribute Scenario)是一种将抽象的质量要求转化为具体、可验证场景的方法,是软件架构设计中非常重要的技术。例如:系统应该具有良好的性能。这个要求过于模糊。可以进一步描述为:在促销活动期间,当系统同时收到10,000 个商品查询请求时,95% 的请求应在 200ms 内完成。
一个完整的质量属性场景通常包括:刺激源(Source)→刺激(Stimulus)→环境(Environment)→系统制品(Artifact)→响应(Response)→度量指标(Measure)。例如:

要素

示例

Source

用户

Stimulus

发起商品查询

Environment

高并发情况下

Artifact

商品查询服务

Response

返回查询结果

Measure

95% 请求 ≤ 200ms

这样,“性能良好”就变成了一个可以通过测试和监控验证的架构目标。因此,在架构设计中应尽量避免:“系统应该具有高性能。”而应该描述为:
“在正常运行条件下,95%的用户请求响应时间不超过200ms。”
2.5 质量属性权衡
不同质量属性之间往往存在冲突,因此架构设计不是简单地追求所有指标最大化,而是在实际约束下进行权衡(Trade-off)。
例如:高安全性与易用性、高性能与强一致性、高可用性与系统成本、高灵活性与系统复杂度存在一定程度的冲突。为提高安全性,可以增加身份验证、权限检查和数据加密,但这些措施可能增加系统响应时间和开发维护成本。又如,为提高可用性,可以部署多个服务实例和数据库副本,但这会增加基础设施成本以及系统运维复杂度。
因此,架构设计需要回答的不是:“哪个质量属性最重要?”而是:“在当前业务目标和约束下,需要优先保证哪些质量属性,以及这种选择会带来什么代价?”这也是架构决策与普通技术选型的重要区别。
架构驱动因素是软件架构设计的出发点。功能需求决定系统需要提供什么能力,质量属性决定这些能力需要达到什么水平,而技术、组织、法规、成本等约束进一步限定了架构设计的选择。可以将本节内容总结为:业务目标→功能需求 + 质量属性 + 约束→架构驱动因素→质量属性场景→架构决策→权衡与验证。
其中,识别架构驱动因素、明确质量属性、将质量要求转化为可验证的质量属性场景,并分析不同质量属性之间的权衡,是软件架构设计的核心工作。
3 架构设计过程与架构决策
软件架构设计的核心不是简单选择某种技术或绘制架构图,而是根据架构驱动因素和质量属性,经过分析、权衡和验证,形成一组能够指导系统实现的关键架构决策。
3.1 架构设计过程
架构设计首先需要回答三个基本问题:1)系统需要达到什么目标?2)哪些需求和质量属性对架构影响最大?3)采用什么结构和技术能够满足这些目标?在实际项目中,可以采用以下基本步骤。
第一,识别架构驱动因素。
从需求中找出对系统结构影响最大的因素,例如,高并发、高可用、数据安全、快速迭代、低成本等。
第二,确定架构策略。
根据架构驱动因素提出候选方案,例如,采用模块化单体、微服务、事件驱动或分层架构。
第三,分析和权衡方案。
比较不同方案对性能、可用性、开发复杂度、成本、运维等方面的影响。
第四,验证关键决策。
对于存在较大技术风险的部分,可以通过原型、Benchmark、性能测试或安全分析进行验证。
第五,记录架构决策。
记录最终选择、选择理由、替代方案以及可能产生的后果,为后续开发和架构演进提供依据。
一个典型的架构设计过程可以概括为:需求与约束→识别架构驱动因素→明确质量属性→识别架构问题→提出候选方案→选择架构模式与策略→技术选型→权衡与验证→形成架构决策→记录并持续演进。
架构设计不是一次性的线性过程,而是一个不断分析—决策—验证—调整的迭代过程。
3.2 架构策略(Architecture Tactics)
架构策略(Architecture Tactics)是针对某个质量属性采取的具体设计措施。它比架构模式更加具体,通常用于解决特定的架构问题。例如,对于不同质量属性,可以采用不同策略:

质量属性

典型架构策略

性能

缓存、并发、异步处理、数据复制

可用性

冗余、故障转移、健康检查

安全性

身份认证、授权、加密、审计

可修改性

模块化、信息隐藏、接口隔离

可扩展性

水平扩展、负载均衡、无状态设计

可靠性

重试、超时、持久化、故障恢复

例如,为提高系统可用性,通过部署多个服务实例和故障转移机制,使单个实例发生故障时系统仍能继续提供服务。
因此可以简单理解: 架构策略 解决“如何改善某个质量属性”的问题。
3.3 技术选型
架构确定了总体方向后,还需要进行技术选型,例如:编程语言、数据库、消息中间件、缓存、Web 框架、容器平台、云服务、AI/LLM 服务。
技术选型不应简单依据“技术是否流行”,而应该根据架构目标进行评价。例如,选择数据库时,需要考虑:业务需求、数据模型、一致性要求、读写模式、数据规模、性能与可用性、成本与运维能力。
因此,技术选型本质上也是一种架构决策。尤其需要避免:先确定技术,再寻找使用技术的理由。正确的过程应该是:先明确问题和约束,再比较技术方案。
3.4 架构决策记录(Architecture Decision Records)
架构设计过程中会产生大量重要决策,例如:为什么采用微服务?为什么选择 PostgreSQL 而不是其他数据库?为什么采用异步消息?为什么使用最终一致性?为什么采用某种 AI 模型?为什么选择 RAG 而不是直接调用 LLM?这些决策如果只存在于架构师或开发人员的头脑中,随着人员变化和项目演进,很容易失去上下文。因此,可以使用 Architecture Decision Record(ADR,架构决策记录)记录重要架构决策。
一个简化的 ADR 通常包括:
标题:采用消息队列处理订单事件
背景(Context):当前订单服务与库存、通知服务存在较强同步依赖,高峰期可能造成请求阻塞。
候选方案(Alternatives)
A. 同步 REST 调用
B. 消息队列
C. 数据库共享
决策(Decision):采用消息队列实现异步事件通信。
理由(Rationale):降低服务之间的时间耦合,提高系统的可扩展性。
后果(Consequences)
优点:解耦、削峰、提高扩展能力。
缺点:增加消息系统运维成本,并引入最终一致性问题。
ADR 最重要的价值不是记录“选择了什么”,而是记录“为什么选择它,以及这个选择带来了什么后果。”这样,当系统未来发生变化时,团队可以重新审视原有决策,而不是重复讨论已经解决过的问题。
架构设计的核心可以概括为:根据架构驱动因素识别问题,通过架构模式确定系统整体结构,通过架构策略解决关键质量属性问题,通过技术选型落实架构方案,并通过架构决策记录保存设计依据。
4 架构风格与现代设计范式
架构风格(Architectural Style)描述软件系统中组件、接口以及交互关系的一类典型组织方式。不同架构风格适用于不同的业务规模、质量属性和技术环境。传统软件系统以分层、模块化和 SOA 为主,现代系统则进一步发展出微服务、事件驱动、云原生以及 AI-Native 等架构范式。
需要注意的是,架构风格不是互相排斥的。实际系统往往组合使用多种风格。例如,一个微服务系统内部可以采用分层设计,服务之间采用事件驱动通信,同时运行在 Serverless 或 Kubernetes 平台上;AI 应用则可能同时使用 RAG、Agent 和 Workflow。
4.1 分层与模块化架构
分层架构(Layered Architecture)将系统按照职责划分为多个层次,每一层只承担相对明确的职责。模块化架构(Modular Architecture)**则强调按照业务职责或变化边界划分独立模块。典型的分层结构为:
其特点:
  • 结构清晰,容易理解;
  • 模块之间职责明确;
  • 适合中小型业务系统;
  • 易于测试和维护。
其主要问题是:如果层次之间依赖过多,或者所有模块最终都依赖同一个数据库,系统仍可能形成较强耦合。
4.2 面向服务的架构(SOA)
面向服务的架构(Service-OrientedArchitecture,SOA)将企业系统中的业务能力组织成相对独立的服务,并通过标准化接口进行通信。典型结构为:
其特点:
  • 强调业务能力复用;
  • 适合大型企业已有多个异构系统的环境;
  • 有利于系统集成和跨系统协作。
SOA 通常强调企业级服务集成和业务能力复用,而微服务更加关注服务的独立开发、部署和演进。因此,二者虽然具有联系,但并不能简单地认为“SOA 就是微服务”。
4.3 微服务架构
微服务架构(Microservices Architecture)将系统划分为一组围绕业务能力组织的、可以独立开发和部署的服务。例如,电商系统:
其特点:
  • 服务可以独立部署;
  • 支持不同服务独立扩展;
  • 适合大型系统和多个开发团队;
  • 服务边界通常围绕业务能力划分。
但微服务也会引入新的复杂性,例如:网络通信;分布式事务;服务发现;故障处理;实现系统组件之间的异步协作。一个组件(构件)产生事件,其他组件根据日志和链路追踪;其运维非常复杂度。因此,微服务并不是“更高级的单体架构”,而是用分布式系统的复杂性换取服务独立性。
4.4 事件驱动的架构
事件驱动的架构(Event-Driven Architecture,EDA)通过事件实现系统组件之间的异步协作。一个组件产生事件,其他组件根据需要订阅和处理事件。
电商订单处理过程如下:用户完成下单后,订单服务发布OrderCreated,库存服务收到事件后扣减库存,通知服务发送短信或邮件,数据分析系统则记录订单数据。订单服务不需要直接调用所有消费者。
事件驱动的架构的特点:
  • 服务之间松耦合;
  • 支持异步处理;
  • 适合高并发和事件流处理;
  • 容易增加新的事件消费者。
但事件驱动系统需要特别关注:消息重复;消息顺序;消息丢失;最终一致性;事件版本管理。因此,事件驱动架构通常需要配合幂等、重试、死信队列和消息持久化等机制。
4.5 云原生架构(Cloud-Native Architecture)
云原生架构是一种面向云计算环境设计和运行软件系统的架构方法。其核心不是简单地“把软件部署到云上”,而是充分利用云平台的弹性、自动化、分布式和按需使用资源等特点,提高系统的可扩展性、可靠性和交付效率。
云原生架构通常包括以下几个方面:
  • 容器化:使用容器封装应用及其运行环境,实现标准化部署。
  • 服务化:按照业务领域划分服务,降低系统之间的耦合。
  • 弹性伸缩:根据业务负载动态增加或减少应用实例。
  • 自动化运维:自动完成部署、扩容、故障恢复和版本更新。
  • 持续交付:通过 CI/CD 实现代码构建、测试和部署的自动化。
  • 可观测性:通过日志、指标和分布式链路追踪监控系统运行状态。
Kubernetes(K8s)是云原生架构中重要的容器编排平台,主要负责容器化应用的部署、调度、扩缩容、服务发现和故障恢复。例如:
需要注意:Kubernetes 不是云原生架构本身,而是实现云原生应用部署和运行的重要基础设施。一句话概括:云原生架构通过容器化、服务化、自动化和弹性等技术与实践,使软件系统能够更好地利用云计算环境,Kubernetes 则负责对这些容器化应用进行统一编排和管理。
4.6 原生AI架构(AI-Native Architecture)
传统软件通常由确定性的程序逻辑驱动,而原生AI架构(AI-Native Architecture) 则将 AI 模型、数据、上下文和推理能力作为系统核心组成部分。一个典型的AI 应用可以表示为:
例:在企业知识问答系统中,用户询问:“公司的报销标准是什么?”系统首先从企业知识库中检索相关制度文档,再由LLM组织回答。
这种典型的RAG(Retrieval-Augmented Generation) 架构,使模型能够利用企业自己的知识,而不是仅依赖模型训练数据。
原生AI架构系统还需要考虑传统软件架构之外的问题,例如:Prompt 与 Context管理;模型选择和路由;向量数据库;AI Gateway;Guardrails;模型评估;Token 和成本控制;AI 安全与数据隐私。
因此,原生AI架构的核心变化,是将“模型 + 数据 + 上下文 + 推理”纳入软件系统的核心架构。
4.7 Agent 与 Workflow
随着生成式AI 的发展,AI 应用已经从简单的“用户提问—模型回答”进一步发展到能够调用工具、执行任务和完成多步骤流程的 Agent 和 Workflow 架构。
4.7.1. Agent 架构
Agent 可以根据目标自主决定下一步行动,并调用外部工具。
例:在智能旅行助手系统中,用户提出:“帮我制定一个周末旅行计划。” Agent 可以执行如下步骤:理解需求→查询天气→搜索景点→查询交通→比较方案→生成旅行计划。这里 Agent 不仅生成文本,还需要调用天气、地图、搜索等外部工具。
因此,Agent 架构需要额外解决:Tool Calling;Agent State;Memory;权限控制;错误恢复;成本控制;Agent Evaluation。
4.7.2. 工作流架构
工作流(Workflow) 则更强调预先定义好的执行流程。例如,自动处理客户投诉:收到投诉→分类→提取订单信息→查询订单→判断问题类型→生成处理方案→人工审核→发送回复。其中每一步都具有明确的输入、输出和执行条件。Agent 与 Workflow 的区别可以简单理解为:

Workflow

Agent

流程

预先定义

可以动态规划

控制方式

程序控制

模型参与决策

可预测性

较高

相对较低

适合场景

固定业务流程

开放性复杂任务

风险控制

相对容易

更复杂

实际系统通常不是二选一,而是将二者结合:
这种Workflow + Agent的组合能够在保持业务流程可控的同时,为部分步骤引入 AI 的动态决策能力。
架构风格部分小结
不同架构风格解决的问题不同,可以形成如下认识:

架构风格

核心思想

典型场景

分层与模块化

职责分离、降低耦合

传统业务系统

SOA

企业业务能力服务化

大型企业系统集成

微服务

服务独立开发、部署和扩展

大型互联网系统

事件驱动

通过事件进行异步协作

高并发、实时数据处理

云原生架构

按需运行、平台管理基础设施

云函数、事件处理

AI-Native

模型、数据和上下文成为核心能力

RAG、AI 应用

Agent

AI 自主规划并调用工具

复杂任务自动化

Workflow

通过确定性流程组织任务

企业业务流程

需要特别强调,现代软件系统往往是多种架构风格的组合,而不是选择其中一种。例如,一个企业 AI 应用可以采用“微服务 +事件驱动 + Cloud + RAG + Agent”的组合架构。
因此,学习架构风格的目的并不是记忆各种架构的名称,而是理解什么问题适合采用什么架构风格,以及不同风格组合后会带来什么能力、复杂性和工程代价。
注意:其它经典的架构风格还包括:客户端—服务器(Client–Server)、管道—过滤器(Pipe-and-Filter)、仓库架构(Repository)、六边形架构(Hexagonal Architecture)等已经融入上述架构中,有兴趣的读者可以单独查阅学习。
5  架构视图
软件架构的复杂性决定了我们无法通过单一的、全局的图纸来完整描述它。就像设计一栋大楼需要结构图、水暖图、电气图一样,软件系统也需要从不同的视角和抽象级别去审视。架构视图(Architecture View)是软件架构在某个特定维度上的表现形式。
为了全面理解系统,我们将通过一个具体的“在线书店系统”(支持用户浏览购买图书、支付结算、物流配送等功能),逐一剖析五大核心架构视图以及主流的架构建模方法,并提供对应的 PlantUML 源码生成的图。
5.1 结构视图(Structural View)
结构视图描述系统由什么组成?它关注系统的静态组织结构,包括代码包、模块、类或微服务组件之间的静态依赖和组合关系。它回答了“代码文件是如何组织和划分的”这一问题。可以用层次结构图表示。
5.2 行为与交互视图(Behavioral & Interaction View)
行为与交互视图描述系统如何运行和协作?它们关注系统在运行时的动态行为。它展示了当特定事件发生时,对象或微服务之间如何通过消息传递、方法调用或事件触发来进行协作。UML顺序图可以作为描述它们的视图。
5.3 数据视图(Data View)
数据是什么、如何存储和流动?数据视图关注系统内部的数据实体、数据结构、持久化存储方案(如关系型数据库、NoSQL、缓存)以及数据在不同模块间的流动与转换规则。数据视图无法用单一图描述,需要多个图配合。比如,UML类图只能表示数据实体的关系,无法表示存储方案。
5.4  部署视图(Deployment View)
部署视图描述软件系统的物理拓扑结构,即软硬件之间的映射,展示最终可执行软件、第三方组件如何安装并运行在物理节点(服务器、网络交换机、移动设备)上。例如,
这里的部署视图就是UML部署图,具体详情可以参看UML部署图的讲解。

UML部署图

公众号:讲理软件第13讲:软件系统建模:部署图
5.5 场景视图(Scenario View)
场景视图是用关键业务场景把其他视图串起来,验证架构能不能真正满足需求。场景视图也常称为用例视图(与UML用例视图相同)或端到端(End-to-End)场景视图。它通常作为“穿针引线”的视角,用来验证前面几个视图是否能够协同支撑核心的业务用例。例如,用户从零开始搜索并完成购书的全链路过程如下。
场景视图主要关注:
① 外部参与者与系统的交互
② 关键业务流程,如登录、下单、支付、退款
③ 跨模块、跨服务的协作过程
④ 架构是否支持这些流程
⑤ 功能需求和非功能需求在具体场景中的体现
⑥ 其他视图之间是否一致、有没有遗漏,
它相当于架构的“故事线” 和 “验收视角”。
5.6 C4模型与4+1视图 
C4 模型由 Simon Brown 提出,核心是 4 个抽象层级,它更适合现代软件团队,尤其是敏捷、微服务、云原生、互联网项目,用于架构沟通、文档、评审和新人入职培训。

C4 层级/图

主要用途

给谁看

System Context 系统上下文图

说明系统边界、外部用户、外部依赖

产品、业务方、非技术干系人

Container 容器图

说明应用、服务、数据库、消息队列、前端等运行单元

技术负责人、开发、运维、架构师

Component 组件图

说明某个容器内部模块划分、职责、接口

开发团队、模块负责人

Code 代码图

说明类、接口、实现关系,通常由 IDE 生成

具体开发者

Dynamic 动态图

说明关键流程,如登录、下单、支付回调

开发、测试、架构评审

Deployment 部署图

说明环境、节点、云资源、网络、集群

运维、SRE、平台团队

注意:C4模型的核心确实是那四个静态结构层级(Context、Container、Component、Code),Dynamic(动态图)和 Deployment(部署图)并不属于这四个核心层级,而是被官方定义为“补充图”(Supplementary Diagrams)。它们存在的目的,是为了弥补核心静态图无法表达的两个关键维度:运行时行为和物理部署拓扑。

4+1 视图模型
4+1 视图是由 Philippe Kruchten 提出的视图模型,它更偏传统软件工程和系统化架构描述,常用于RUP、大型企业系统、嵌入式/实时系统、复杂系统、教学和正式架构文档。详情总结在下表中。

视图

主要用途

给谁看

逻辑视图 Logical

描述功能、对象模型、类、包、职责

设计者、开发者

进程视图 Process

描述并发、线程、进程、同步、消息、性能

系统集成者、性能工程师

开发视图 Development

描述模块、库、构建、代码组织、配置管理

程序员、项目经理

物理视图 Physical

描述硬件、节点、网络、部署拓扑

系统工程师、运维

场景/用例视图 Scenarios

用关键用例串联并验证其他四个视图

所有干系人

6 系统分解、领域架构与数据架构
软件架构设计的核心任务之一,是将一个复杂的软件系统划分为职责清晰、边界明确、相互协作的组成部分。系统分解解决“系统由哪些部分组成”的问题,模块化解决“各部分如何组织和复用”的问题,领域驱动架构解决“如何按照业务概念划分系统”的问题,而服务边界、数据架构和数据一致性则进一步解决“各部分如何协作以及如何管理数据”的问题。
以一个在线电商系统为例,系统通常包含用户、商品、购物车、订单、支付、库存、物流等业务能力。如果将所有功能放在一个大型模块中,随着业务发展,系统会逐渐变得难以理解、修改和测试。因此,需要从系统分解、业务领域和数据等多个层次对系统进行架构设计。
6.1 系统分解
系统分解是指将一个规模较大的软件系统按照功能、业务职责或技术职责划分为若干相对独立的子系统或组件。系统分解的主要目标包括:
  • 降低复杂度:将一个复杂问题分解为多个规模较小的问题。
  • 明确职责:使每个子系统承担相对集中的职责。
  • 控制依赖:减少组件之间不必要的耦合。
  • 便于开发和测试:不同团队可以针对不同模块开展开发、测试和维护工作。
  • 支持系统演进:当某一业务发生变化时,可以尽量将变化限制在相关模块内部。
例如,电商系统可以进行如下一级分解:
电商系统
     ├── 用户子系统
     ├── 商品子系统
     ├── 购物车子系统
     ├── 订单子系统
     ├── 支付子系统
     ├── 库存子系统
     └── 物流子系统
需要注意的是,系统分解并不意味着每个子系统最终都必须部署成独立的微服务。对于规模较小的系统,这些子系统完全可以作为一个单体应用中的不同模块存在。逻辑上的边界与物理上的部署边界是两个不同的问题。
6.2 模块化
模块化是在系统分解基础上进一步组织软件结构的方法。一个模块通常具有明确的职责,并通过定义良好的接口与其他模块协作。良好的模块化设计通常遵循两个基本原则:高内聚、低耦合。
高内聚意味着一个模块内部的功能具有较强的关联性。例如,订单创建、订单状态管理和订单查询等功能具有共同的业务目标,可以组织在订单模块中。
低耦合意味着模块之间尽可能减少直接依赖。例如,订单模块需要调用库存模块检查库存时,可以依赖库存模块提供的接口,而不应该直接访问库存模块的内部数据结构。可以定义如下接口:在订单服务模块OrderService中,它包含createOrder()、 cancelOrder()、  queryOrder()等功能模块,在InventoryService中,它包含  checkStock()、 reserveStock()、releaseStock()等功能模块。订单模块只需要知道InventoryService 提供什么能力,而不需要知道库存数据究竟存储在哪个数据库表中。
模块化还需要关注封装性。模块应隐藏内部实现细节,只暴露完成业务职责所必需的接口。这样,当模块内部的数据库结构、算法或技术实现发生变化时,可以尽量避免影响其他模块。
6.3 领域驱动架构
当系统规模进一步扩大,仅按照技术功能进行划分可能仍然难以保持清晰的业务边界。因此,可以从业务领域的角度进行架构设计。领域驱动设计(Domain-Driven Design,DDD)强调以业务领域和业务概念作为软件模型的重要基础。其核心思想之一,是让软件结构尽可能反映现实业务结构。以电商系统为例,可以识别出若干核心领域:
电商业务领域
├── 用户域
├── 商品域
├── 交易域
│         ├── 购物车
│         └── 订单
├── 库存域
├── 支付域
└── 物流域
不同领域具有不同的业务规则。例如:商品域负责商品信息、价格、上下架等业务;订单域负责订单创建、订单状态流转和订单取消;库存域负责库存数量、库存预占和库存释放;支付域负责支付单、支付状态以及支付结果处理;物流域负责配送信息和物流状态。
领域划分的一个重要原则是:业务规则应该尽量归属于拥有这些规则的领域。例如,“订单取消后释放预占库存”涉及订单和库存两个领域。如果简单地将库存修改代码直接写入订单模块,会使订单模块逐渐了解库存领域的内部实现。更合理的方式是由订单领域产生“订单已取消”这一业务事实,再由库存领域根据这一事实执行相应的库存释放操作。
6.4 服务边界
服务边界是指系统中一个服务或模块所负责的业务范围,以及它与其他服务之间的交互范围。确定服务边界时,不能简单地按照数据库表或者代码文件数量进行划分。例如,将“订单表”单独部署为一个服务,并不意味着形成了合理的订单服务。
合理的服务边界通常需要综合考虑以下因素:
业务职责:服务是否具有相对完整的业务职责?
业务规则:相关业务规则是否需要在同一边界内保持一致?
数据所有权:哪些数据由该服务负责维护?
变化原因:具有相似变化原因的功能是否属于同一边界?
协作方式:服务之间是否需要频繁进行同步调用?
团队职责:不同团队是否需要独立开发、测试和发布?
例如,在电商系统中,可以将订单和库存划分为两个服务:
   订单服务
│
│ 取消订单
▼
  库存服务
│
└── 释放库存
此时,订单服务拥有订单数据的管理权,库存服务拥有库存数据的管理权。订单服务不应该直接修改库存服务的数据表,而应该通过服务接口或领域事件与库存服务协作。
服务边界一旦确定,通常也意味着数据访问边界随之确定。一个重要的架构原则是:服务之间共享业务数据,不等于共享数据库表。
6.5 数据架构
数据架构解决系统中的数据如何组织、存储、访问和流动的问题。它不仅包括数据库选型和表结构设计,还包括数据所有权、数据模型、数据访问方式以及数据在不同模块之间的传递方式。
在电商系统中,可以建立如下数据所有权关系:

领域/服务

主要数据

数据所有者

用户

用户、地址、账户信息

用户服务

商品

商品、分类、价格

商品服务

订单

订单、订单项、订单状态

订单服务

库存

库存数量、库存预占记录

库存服务

支付

支付单、支付状态

支付服务

物流

运单、物流状态

物流服务

这种设计强调数据所有权。例如,订单服务需要显示商品名称和价格,但这并不意味着订单服务可以直接修改商品服务中的商品数据。对于订单而言,商品价格还存在一个特殊问题。假设用户下单时商品价格为100元,之后商品价格调整为120元,那么历史订单通常仍然需要保留100元的成交价格。因此,订单数据中应保存与交易相关的价格快照,而不能简单地在查询历史订单时始终读取商品当前价格。
这说明数据架构不仅是数据库表结构设计,更是对业务数据生命周期和业务语义的建模。
6.6 数据一致性
当一个系统由多个模块或服务组成后,数据一致性会成为架构设计中的重要问题。在单体系统中,一个事务通常可以同时修改订单、库存等多张数据表,因此可以比较容易地使用数据库事务保证一致性。但在分布式系统中,订单服务和库存服务可能使用不同的数据库,此时一个数据库事务无法简单地覆盖两个服务。
例如,用户购买商品时可能发生以下操作:创建订单→锁定库存→发起支付→支付成功→确认订单。这些操作可能分别由不同的服务完成。如果其中某一步失败,就需要考虑其他操作已经产生的数据如何处理。
因此,系统设计中应首先明确一致性的业务要求,而不是简单追求所有数据始终保持强一致。对于不同的数据,可以采用不同的一致性策略:
  • 强一致性:操作完成后,相关数据必须立即达到一致状态。适用于对一致性要求非常高的核心业务场景。
  • 最终一致性:不同服务中的数据允许在短时间内存在差异,但经过消息传递、重试等机制后最终达到一致。
  • 补偿机制:当一个业务流程部分成功、部分失败时,通过反向操作或其他业务手段恢复到可接受状态。
  • 幂等机制:同一个请求重复执行时,不会产生重复的业务结果。例如,支付结果通知可能重复发送,订单服务需要能够安全地处理重复通知。又如,库存服务收到“订单取消”事件后释放库存。如果同一个事件因为网络重试而被消费两次,库存不能被错误地释放两次。因此,库存服务可以通过订单号、事件编号等建立幂等控制。
由此可以看到,数据一致性并不是单纯的数据库问题,而是与业务流程、服务边界、消息机制、事务模型和异常处理密切相关。
7 可靠性、安全性与可观测性架构
软件架构不仅决定系统如何实现功能,还决定系统在异常、攻击、性能波动和长期运行环境下能否持续提供服务。因此,在进行软件架构设计时,需要同时考虑可靠性(Reliability)、韧性(Resilience)、安全性(Security)、可观测性(Observability)以及运维能力(Operations)。这些质量属性会直接影响系统的组件划分、数据流、部署方式、故障处理机制以及运行管理方式。
7.1 可靠性
软件可靠性是指系统在规定条件和规定时间内持续正确提供服务的能力。可靠性要求会影响架构中的冗余设计、数据持久化、事务处理、错误处理和故障恢复机制。例如,对于不能轻易中断的系统,可以通过服务冗余、数据库备份、故障转移等方式降低单点故障的影响。在架构设计阶段,应重点考虑:
  • 避免关键组件形成单点故障;
  • 对重要数据进行持久化和备份;
  • 设计合理的异常处理和恢复机制;
  • 明确服务可用性和可靠性目标;
  • 通过自动化测试和持续交付降低软件缺陷引起的故障。
因此,可靠性不是某个模块单独承担的功能,而是贯穿系统架构、实现和运行全过程的一项质量属性。
7.2 Resilience(韧性)
韧性强调系统面对故障、异常负载和外部环境变化时,仍能够维持核心服务,或者在发生故障后快速恢复的能力。可靠性关注“系统能否持续正常工作”,而韧性进一步关注“系统发生故障时如何应对”。
例如,一个服务发生故障时,其他服务是否能够继续运行;网络暂时不可用时,系统是否能够重试或降级;部分组件失效时,是否能够进行故障隔离。
常见的架构措施包括:超时(Timeout);重试(Retry);熔断(Circuit Breaker);限流(Rate Limiting);降级(Graceful Degradation);故障隔离(Fault Isolation);主备或多副本部署;自动恢复和故障转移。
因此,韧性架构的核心思想是:不能假设系统中的所有组件始终正常,而应设计系统在部分组件失效时仍能保持可接受的服务能力。
7.3 安全架构
安全架构是将安全要求落实到软件架构中的整体设计,包括身份认证、访问控制、数据保护、通信安全以及安全审计等。安全需求会直接影响系统的组件划分和数据流。例如,需要对不同用户提供不同访问权限时,架构中就需要引入身份认证和授权机制;敏感数据在网络中传输时,需要考虑加密通信;重要操作发生后,还需要保留审计记录。安全架构通常需要考虑:
  • 身份认证(Authentication);
  • 授权与访问控制(Authorization);
  • 数据加密与密钥管理;
  • 网络和接口安全;
  • 输入验证与攻击防护;
  • 日志与安全审计;
  • 敏感数据保护;
  • 安全漏洞检测和补丁管理。
安全性应尽可能在架构设计早期考虑,而不是在系统开发完成后再通过外围措施补充。安全架构的目标是在保证系统功能的同时,降低未经授权访问、数据泄露和恶意操作等安全风险。
7.4 Observability(可观测性)
可观测性是指通过系统产生的外部信息了解系统内部运行状态和问题原因的能力。对于复杂的软件系统,仅依靠功能测试无法发现所有运行问题。因此,架构需要从一开始就设计日志、指标和分布式追踪等机制,使开发人员和运维人员能够回答“系统现在发生了什么”和“为什么会发生”。
可观测性通常包括三个重要方面:
  • 日志(Logs):记录系统运行过程中发生的事件和错误;
  • 指标(Metrics):以数值形式反映系统状态,例如请求数量、响应时间和错误率;
  • 追踪(Traces):记录一次请求在多个服务之间的调用过程。
良好的可观测性架构可以帮助团队及时发现异常、定位故障、分析性能瓶颈,并为系统优化和容量规划提供依据。因此,可观测性不仅是运维工具的功能,也是软件架构的重要组成部分。
7.5 面向运维的架构(Architecture for Operations)
面向运维的架构强调软件系统不仅要“能够开发和运行”,还应当“容易部署、监控、升级、维护和恢复”。传统架构设计容易过多关注业务功能,而忽略系统长期运行过程中的运维成本。面向运维的架构则需要从系统生命周期的角度考虑自动化部署、配置管理、监控告警、故障恢复和版本升级等问题。常见的设计内容包括:
  • 自动化构建、测试和部署;
  • 配置与代码分离;
  • 健康检查和自动故障发现;
  • 监控、日志和告警;
  • 灰度发布、滚动升级和快速回滚;
  • 备份、恢复和灾难恢复;
  • 基础设施和部署环境的自动化管理。
从整体上看,可靠性、安全性、可观测性和运维能力相互关联:可靠性关注系统持续正确运行,韧性关注系统面对故障的应对能力,安全架构关注系统抵御安全威胁的能力,可观测性帮助发现和分析系统状态,而面向运维的架构则将这些能力落实到系统的日常运行和维护过程中。
因此,在现代软件工程中,架构设计不应只回答“系统如何实现功能”,还应回答“系统出现异常时怎么办、受到攻击时怎么办、运行出现问题时如何发现,以及如何持续地维护和演进系统”。
8 软件架构设计评估、验证、风险与演进
软件架构确定了系统的基本结构、主要组件及其关系,对系统的性能、可靠性、安全性和可维护性等具有重要影响。因此,在进入大规模开发之前,需要对架构设计进行评估和验证,以尽早发现架构缺陷和风险,降低后期修改成本。
8.1. 软件架构设计评估
软件架构设计评估是根据系统需求和质量属性,对架构方案的合理性、可行性及潜在风险进行分析和判断。评估的核心是回答:架构是否满足需求,以及是否存在影响系统质量的重大风险。架构评估主要包括以下内容:
需求符合性
检查架构是否覆盖系统的主要功能需求和非功能需求,特别是性能、可用性、安全性、可扩展性等关键质量属性。
架构合理性
分析系统边界、模块划分、组件职责和依赖关系是否清晰合理,是否存在过度耦合、循环依赖、单点故障等问题。
质量属性分析
重点评估架构对关键质量属性的支持能力。
例如:性能:吞吐量、响应时间是否满足要求;可用性与可靠性:组件故障时系统能否继续提供服务;可扩展性:系统能否随着用户、数据和业务规模增长进行扩展;安全性:身份认证、访问控制、数据保护等是否得到合理设计;可维护性:系统是否易于修改、测试和演进。
风险与权衡分析
识别架构中的关键风险,并分析不同架构方案之间的权衡。例如,高可用性通常会增加系统复杂度和成本,强一致性可能影响系统性能和可扩展性。架构评估应明确这些决策及其影响。
常用的评估方法包括架构评审、场景分析、风险分析和候选方案比较等。评估结果应形成明确的结论和风险清单,为架构修改和决策提供依据。
8.2. 软件架构设计验证
软件架构设计验证是通过原型、实验和测试等手段,获得客观证据,验证架构设计是否能够满足预期的需求和质量属性。验证的核心是回答:架构设计是否能够在实际运行条件下达到预期目标。架构验证主要包括以下内容:
原型验证(PoC)
对存在技术不确定性的关键架构决策建立原型,通过实验验证技术可行性。例如,验证数据库、消息队列或通信技术是否能够满足预期的性能要求。
性能验证
通过负载测试、压力测试和容量测试等方法,验证系统的吞吐量、响应时间和资源使用情况是否达到设计目标。
可靠性与容灾验证
通过故障注入和故障演练,模拟服务、数据库、网络等组件发生故障的情况,验证系统的故障检测、故障切换、降级和恢复能力,并验证 RTO、RPO 等指标。
安全验证
通过安全测试、漏洞扫描、权限测试等手段,验证身份认证、访问控制、数据加密等安全设计是否有效。
验证结果分析
将实际验证结果与架构目标进行比较。如果验证结果不能满足要求,应重新分析架构设计,调整架构方案并再次验证。
因此,架构评估与验证形成一个持续迭代的过程:需求与质量属性→ 架构设计 → 架构评估 → 风险识别 → 原型/测试验证 → 架构改进 → 再评估与验证。
架构评估侧重于分析和判断架构是否合理,架构验证侧重于通过实验和测试获得架构可行性的证据。二者结合,可以在系统开发早期发现重大架构问题,为后续软件设计、开发和部署提供可靠基础。
8.3软件架构风险与演进
软件架构风险是指由于架构设计中的技术选择、结构缺陷或外部环境变化,可能导致系统无法满足预期需求的因素。常见的架构风险包括性能瓶颈、单点故障、系统耦合度过高、技术选型不合理、安全隐患以及扩展能力不足等。架构设计阶段应及时识别和分析这些风险,并通过架构调整、原型验证、测试等方式降低风险。
软件架构并不是一次设计完成后永久不变的。随着业务需求、用户规模、数据规模和技术环境不断变化,原有架构可能逐渐无法满足新的要求,因此需要进行架构演进。架构演进通常包括模块重构、技术升级、服务拆分、数据架构调整以及部署架构优化等。架构演进应遵循渐进式、可验证和风险可控的原则,在满足当前需求的同时,为未来变化保留合理的扩展空间。
因此,软件架构设计不仅要关注系统当前的实现,还应持续关注架构风险,并根据系统的发展进行评估和演进。

9 软件架构设计文档模板

1. 引言

1.1 编写目的

说明本文档的目的、目标读者以及文档的使用范围。

1.2 项目背景

简要介绍系统建设背景、业务目标和建设意义。

1.3 系统范围

说明系统包含的功能范围、边界以及不属于本系统的内容。

1.4 术语与缩略语

解释文档中使用的重要术语和缩略语。

2. 需求与架构目标

2.1 功能需求

概述系统需要实现的主要功能。

2.2 非功能需求

说明系统的主要质量属性要求,例如:性能、可用性、可靠性、安全性、可扩展性、可维护性。

2.3 架构目标与约束

说明架构设计需要达到的目标,以及技术、业务、成本、组织等方面的约束条件。

3. 总体架构设计

3.1 架构原则

说明架构设计遵循的主要原则,例如高内聚低耦合、分层设计、最小权限等。

3.2 架构风格

说明采用的主要架构风格,如分层架构、微服务架构、事件驱动架构等。

3.3 系统上下文

描述系统与用户、外部系统以及第三方系统之间的关系。

3.4 总体架构图

给出系统整体结构,展示主要组件及其关系。

4. 详细架构设计

4.1 模块/组件设计

说明系统主要模块或组件及其职责。

4.2 模块关系与依赖

描述模块之间的调用、依赖和协作关系。

4.3 接口设计

说明主要模块之间以及系统与外部系统之间的接口。

4.4 关键业务流程

通过流程图或时序图描述核心业务场景的运行过程。

5. 数据架构设计

说明系统中的主要数据及其管理方式,包括:核心数据模型、数据存储、数据流转、数据一致性、数据备份与恢复、数据安全。

6. 部署与运行架构

描述系统实际运行环境,包括:服务器或云资源、网络结构、数据库、缓存、消息中间件、容器/集群、负载均衡、高可用与灾备等,并给出部署架构图。

7. 关键技术与架构决策

说明主要技术选型及其原因,包括:技术栈、数据库、中间件、通信方式、第三方服务、关键架构方案。对于重要决策,应说明候选方案、选择理由、优缺点及可能影响。

8. 质量属性设计

说明架构如何满足关键质量属性,重点包括:

质量属性

设计目标

主要架构措施

性能

满足目标吞吐量和响应时间

缓存、异步、水平扩展

可用性

满足系统可用性要求

集群、故障切换

安全性

保护系统和数据

认证、授权、加密

可扩展性

支持业务规模增长

模块化、水平扩展

可维护性

降低修改和维护成本

高内聚、低耦合

可观测性

支持故障发现和定位

日志、监控、链路追踪

9. 架构评估与验证

说明如何确认架构设计满足要求。

9.1 架构评估

包括:需求符合性分析、架构合理性分析、质量属性分析、风险分析、架构方案权衡。

9.2 架构验证

包括:原型验证、性能测试、可靠性和故障测试、安全测试、灾备验证、记录关键验证结果和遗留问题。

10. 风险与演进

10.1 架构风险

列出当前架构存在的主要风险及其影响。

10.2 风险应对措施

说明风险的规避、降低或监控措施。

10.3 架构演进

说明未来业务规模扩大、技术升级或需求变化时的架构演进方向。

11. 附录

包括:

  • 架构图

  • 数据模型

  • 接口清单

  • 术语表

  • 架构决策记录(ADR)

  • 测试和验证结果

  • 其他参考资料

相关学习资料