跳至正文

2026 年 8 月 8 日 · 阅读时长 28 分钟

软件架构师的 19 个核心领域:边界与选型

架构工作的产物是一组可解释、可验证的技术决策:系统如何划分边界,数据由谁负责,组件怎样通信,失败时如何恢复,变更怎样发布,运行状态如何被观察。

这 19 个领域覆盖架构方法、设计模式、通信协议、数据系统与运行平台,但它们解决的问题并不在同一层。六边形架构解决依赖方向,Kafka 处理持久化事件流,Kubernetes 管理容器工作负载,OpenTelemetry 统一遥测数据;四者服务于不同问题,不能互相替代。

全文按 19 个领域展开,其中「韧性设计」同时覆盖高并发与高可用,包括限流、熔断、降级、负载均衡、CAP 与共识算法。

这 19 个领域可以按上述顺序学习,也可以从当前系统最明显的约束切入。每一节都回答三个问题:它解决什么问题,常见方案如何分工,什么情况下不应增加这层复杂度。

1. 架构基础:结构、质量属性与演进

软件架构描述系统的重要结构、组件职责、交互关系和约束。代码目录只是结构的一部分;部署单元、数据所有权、故障边界、安全边界和团队责任同样属于架构。

架构决策通常围绕质量属性展开:可用性、延迟、吞吐量、一致性、安全性、可维护性、可测试性、可部署性和成本。目标之间经常互相制约。例如,多副本可以提高读取能力和容错能力,却会引入复制延迟、故障切换和一致性判断。

常见演进方式体现的是约束变化,不是一条必须按顺序升级的技术路线:

  • 单体把功能放在一个部署单元中,调用简单、事务直接,适合边界尚未稳定或团队规模较小的系统。

  • MVC 与分层架构组织单体内部职责。MVC 关注输入、模型和视图协作,并不决定系统是否分布式。

  • SOA通过服务契约复用企业能力,常伴随集中治理和集成基础设施。微服务进一步强调围绕业务能力拆分、独立部署与团队所有权。

  • 云原生关注容器、声明式配置、自动化、弹性和可观测的运行方式。单体同样可以运行在云原生平台上。

  • Serverless把部分容量管理和运行时交给平台,适合事件驱动、流量波动大或执行时间较短的任务,同时要评估冷启动、运行限制、可移植性与计费模型。

模块化单体常是更稳妥的起点。只有当独立扩缩容、故障隔离、发布节奏或团队所有权已经形成明确边界时,拆分服务才会带来足以覆盖分布式成本的收益。

2. 经典方法:边界、领域、读写与历史

六边形架构、Clean Architecture、DDD、CQRS 与 Event Sourcing 经常并列出现,实际分属不同层次。

方法主要问题核心做法采用边界
六边形架构业务逻辑如何隔离外部技术业务核心定义 Port,数据库、HTTP、消息等 Adapter 在外层实现简单 CRUD 不必为每个动作创建接口
Clean Architecture源码依赖应指向哪里依赖指向更稳定的业务规则,框架与设备位于外层圆环数量不应机械映射成目录层数
DDD复杂业务如何形成可执行模型统一语言、Bounded Context、Aggregate、Entity、Value Object 与 Domain Event业务规则简单时只使用必要概念
CQRS同一模型难以同时服务写入约束与复杂查询分离 Command 与 Query 模型不要求拆成两个服务或两个数据库
Event Sourcing如何保留状态变化的完整历史追加事件并由事件重建当前状态,投影生成查询模型事件版本、重放、快照和隐私删除成本较高

它们可以组合。一个 Bounded Context 内部可以使用六边形架构控制依赖,部分聚合采用 CQRS,少数确实需要完整审计与时态查询的聚合再使用 Event Sourcing。Event Sourcing 与 CQRS 也能单独采用,没有必须绑定的关系。

边界的有效性最终由代码和运行时共同证明:内部模型不泄漏数据库对象,跨边界调用使用稳定契约,失败语义能被测试,团队也能独立理解和修改对应模块。

3. 软件设计原则:控制变化传播

SOLID 用于检查模块的职责、替换能力和依赖方向:

原则设计问题常见失败信号
SRP,单一职责一个模块因哪类原因变化同一个类同时处理规则、持久化、协议与展示
OCP,开闭原则新行为能否通过稳定扩展点加入每增加一种类型都修改多处分支
LSP,里氏替换子类型是否遵守父类型承诺替换实现后出现额外异常、前置条件或语义变化
ISP,接口隔离使用方是否只依赖需要的能力实现类被迫提供空方法,测试替身需要模拟无关行为
DIP,依赖倒置高层策略是否依赖稳定抽象业务逻辑直接绑定数据库驱动、HTTP SDK 或框架对象

另外几组原则控制设计规模:

  • DRY消除同一知识的重复表达。两段相似代码承载不同业务含义时,过早合并反而会制造耦合。

  • KISS优先选择团队能读懂、测试和运维的最小方案。

  • YAGNI推迟尚无真实需求的扩展点、配置项与基础设施。

  • 高内聚、低耦合让同一业务能力集中在边界内,并减少跨边界需要同时修改的知识。

  • IoC 与 DI把对象创建和依赖装配移到 Composition Root。构造函数注入通常足够,DI Container 只在装配规模确实需要时加入。

原则之间也会发生冲突。为了 OCP 预先抽象所有变化,可能违反 KISS 与 YAGNI。更可靠的做法是先识别稳定业务规则和已经发生的变化,再为它们建立接口。

4. 设计模式:为重复问题建立共同语言

模式用于描述反复出现的结构和协作方式。采用模式之前,要能指出它消除的条件分支、依赖传播或生命周期问题。

类别模式适合处理的问题主要风险
创建型Singleton进程内确实只有一个生命周期的资源或注册表隐藏全局状态、并发与测试依赖;优先由容器管理作用域
创建型Factory根据类型、配置或协议选择具体实现工厂变成包含所有业务规则的大型分支
创建型Builder分步骤构造参数多、存在组合校验的对象简单对象增加无意义样板代码
创建型Prototype从成本较高的预配置对象复制新实例浅复制共享可变状态或资源句柄
结构型Adapter把外部协议转换为内部稳定接口外部字段继续泄漏到领域模型
结构型Decorator在不修改核心实现时叠加缓存、日志或权限多层包装后调用顺序和错误来源难以判断
结构型Proxy控制远程、延迟加载、访问或生命周期远程调用伪装成本地调用,延迟与失败被隐藏
行为型Strategy在同一目标下替换计价、路由或校验算法每个微小差异都创建一个策略类
行为型Observer一个事实发生后通知多个订阅方顺序、重复投递和失败处理缺少定义
行为型Chain of Responsibility按顺序执行验证、过滤或审批节点隐式顺序过长,跳过和终止条件不清晰

模式名称只负责建立共同语言。实现仍需明确输入、输出、错误、幂等性、线程安全和观测方式。

5. 系统设计:接口与通信模型

通信方式应由调用关系、延迟、兼容性和失败处理决定。

方式适合的问题需要明确的边界
REST面向资源的 HTTP API、缓存与统一语义URI、HTTP method、状态码、幂等与版本策略
RPC面向操作的服务调用超时、重试、序列化、错误模型与接口演进
GraphQL客户端需要按视图组合字段和关联数据查询复杂度、N+1、字段权限与缓存
gRPC强类型内部调用、低开销序列化与流式通信Protocol Buffers 演进、HTTP/2 基础设施与浏览器接入
WebSocket客户端与服务端持续双向通信连接状态、心跳、背压、重连与横向扩展
SSE基于 HTTP 的服务端单向事件推送断线续传、代理超时、连接数与事件 ID
API Gateway统一入口、路由、认证、限流与协议适配避免把业务编排全部集中到网关
OpenAPI描述 HTTP API 契约并生成文档或代码需要由 CI 检查规范与实现是否漂移

REST 是架构风格,HTTP 提供传输语义;RPC 是调用模型,gRPC 是一种具体实现;OpenAPI 描述契约,不执行请求。把这些概念分开后,系统可以在外部公开 REST 或 GraphQL,在内部对低延迟服务使用 gRPC,并通过事件处理跨服务的异步变化。

同步调用会把下游延迟和可用性带入当前请求。增加重试前必须确认操作幂等,并设置总时间预算、退避与重试上限。异步消息可以隔离峰值和暂时故障,但会引入重复投递、乱序、积压和最终一致性。

6. 数据库架构:先确定数据所有权

数据库选型先回答四个问题:事务边界在哪里,查询形态是什么,数据规模如何增长,故障后允许丢失或延迟多少数据。

MySQL 的扩展顺序

MySQL 常见扩展顺序是索引与 SQL 优化、连接池治理、主从复制、读写分离,最后才评估分库分表。

  • 主从复制现在也常写作 source/replica。副本可以承担只读查询和故障恢复,但复制延迟会影响「写后立即读」等一致性要求。

  • 读写分离可以在应用或代理层实现。事务内查询、强一致读取和刚写入的数据通常仍需访问主库。

  • 分库分表增加路由、全局唯一 ID、跨分片查询、扩容迁移和分布式事务成本。单表数据量与真实瓶颈尚未达到阈值时,不应提前拆分。

其他数据库的定位

系统更合适的工作负载需要评估的限制
PostgreSQL复杂事务、关系查询、扩展类型与丰富 SQL 能力扩展方式、连接数和高可用方案需要单独设计
ClickHouse列式分析、聚合与高吞吐写入高频小事务更新和逐行 OLTP 不是主要目标
TiDBMySQL 协议兼容、分布式 SQL、横向扩展与强一致事务跨节点延迟、热点、执行计划与运维复杂度
OceanBase分布式关系事务、多副本与大规模在线业务部署资源、兼容模式、分区设计与团队经验

一套系统可以同时使用 OLTP 数据库、分析数据库和搜索索引,但业务事实需要唯一权威来源。ClickHouse 或 Elasticsearch 中的派生数据应能从源数据重建,并有明确的延迟与校验指标。

7. 缓存架构:用命中率换取一致性成本

Redis 常用的 6 类数据类型是 String、Hash、List、Set、Sorted Set 和 Stream。它还提供 Bitmap、Bitfield、Geospatial、HyperLogLog 等能力,因此「6 大数据结构」只能理解为高频集合。

类型典型用途容易忽略的问题
String对象缓存、计数器、分布式状态大 Key、序列化成本、非原子读改写
Hash字段化对象、局部更新字段过多和过期粒度
List双端队列、有限时间线阻塞消费与可靠投递语义有限
Set去重、标签、集合运算大集合运算阻塞与内存占用
Sorted Set排行榜、延时调度、按分值检索热点更新和分值精度
Stream持久化消息流、Consumer GroupPending、确认、裁剪和重复消费

Redis Cluster 使用 Hash Slot 分片,并通过副本和故障转移提高可用性。它不能自动提供跨任意 Key 的强事务,也不能消除网络分区期间的一致性取舍。

多级缓存把不同范围的数据放到离使用方最近的位置:

并非每个请求都要穿过全部缓存层。公开资源适合 CDN,短期页面响应可以使用 Nginx microcache,单实例高频配置适合 Caffeine,跨实例共享数据适合 Redis。

Cache Aside 是常见起点:读取未命中时访问数据库并回填,写入数据库后删除缓存。仍需处理缓存击穿、穿透、雪崩和热 Key,可以按问题选择请求合并、负缓存、Bloom Filter、TTL 抖动、预热或热点拆分。缓存失效策略必须先于缓存层数设计。

8. 消息队列:把时间与故障解耦

系统主要优势更合适的用途重点成本
Kafka分区日志、高吞吐、保留与重放事件流、日志、CDC、流处理输入分区顺序、Consumer Lag、再均衡与容量规划
RabbitMQExchange 路由、确认机制与成熟的工作队列语义任务分发、复杂路由、请求削峰队列堆积、投递确认、死信与集群拓扑
RocketMQ顺序消息、事务消息、延时消息等业务能力交易与事件驱动业务Topic/Queue 规划、重试与运维生态
PulsarBroker 与 BookKeeper 存储分离、多租户与分层存储多租户消息与流平台、长期积压组件数量、BookKeeper 运维与容量模型
Redis Stream能复用 Redis,提供 Stream 与 Consumer Group中小规模内部事件、轻量任务流保留策略、Pending 恢复和 Redis 资源竞争

选型前先写出消息语义:消息是 Command 还是 Event,顺序需要覆盖单个 Key、单个分区还是全局,允许至少一次还是至多一次投递,消费者如何幂等,失败何时重试或进入死信队列,积压多久后触发告警。

「Exactly once」通常只覆盖特定产品和处理边界。消息系统、数据库与外部 API 组成完整业务操作时,仍需要业务唯一键、幂等记录、Outbox 或状态机保证重复执行安全。

9. 微服务:围绕业务能力建立独立运行边界

一组常见的 Spring Cloud 组件可以这样分工:

  • Nacos、Consul、Eureka提供服务注册与发现。Nacos 还提供配置管理,Consul 还覆盖健康检查与 KV 等能力。

  • OpenFeign是声明式 HTTP Client,用 Java interface 描述 HTTP 调用。它不定义一套新的 RPC 传输协议。

  • Sentinel提供流量控制、熔断降级和系统保护等能力。

  • Spring Cloud Gateway处理入口路由、Filter、认证集成和限流等横切职责。

这些组件来自不同生态,不需要全部组合。Kubernetes Service 已经提供服务发现时,额外注册中心要有独立配置、跨集群发现或非 Kubernetes 工作负载等明确理由。

微服务边界应与业务能力、数据所有权和团队责任一致。每个服务独立发布,却共同写同一组核心表,会把部署边界与事务边界分开,形成更难治理的分布式单体。

落地微服务还需要同时设计契约版本、超时预算、重试与熔断、异步一致性、配置与 Secret、日志与 Trace、发布回滚、容量和故障演练。注册中心只能解决「实例在哪里」,无法解决这些运行问题。

10. 云原生:管理可重复的工作负载

Docker Image 保存应用及运行依赖,Container 是 Image 的运行实例。镜像应保持可重复构建、最小依赖、非 root 运行,并通过外部配置注入环境差异。

Kubernetes 的常用对象各自承担明确职责:

对象职责注意事项
Pod最小调度单元,共享网络与部分存储Pod 可替换,不应依赖本地临时状态
Deployment管理无状态 Pod 副本与滚动更新Readiness、资源请求和更新策略决定发布质量
Service为一组 Pod 提供稳定访问入口选择器、端口与流量策略需要和工作负载一致
Ingress描述集群外部 HTTP/HTTPS 路由Ingress API 已冻结,新能力优先评估 Gateway API
ConfigMap保存非敏感配置配置变更是否热加载由应用和挂载方式决定
Secret保存敏感数据Base64 不是加密,需要启用静态加密和最小权限
HPA根据指标调整副本数指标延迟、冷启动和下游容量会影响扩容效果

容器与 Kubernetes 提供运行基础,应用仍需遵守无状态、健康检查、优雅退出、资源限制、幂等任务和可观测性要求。数据库、消息系统等有状态工作负载是否放入集群,应根据备份恢复、存储性能和运维能力单独判断。

11. DevOps:让每次变更都可验证、可追溯

DevOps 关注开发与运行反馈的连续性。工具可以沿着变更过程分工:

  1. Git保存可审查的变更历史。

  2. GitFlow使用 feature、develop、release 与 hotfix 等分支支持计划式版本发布。高频持续交付团队通常更适合短分支和 Trunk-Based Development,避免长期分支合并成本。

  3. CI在每次变更上执行格式、静态分析、测试、安全扫描与构建。

  4. CD把同一构建产物按环境推进,并保留审批、回滚与审计记录。

  5. Jenkins 或 GitHub Actions承载 Pipeline。选型取决于托管方式、插件治理、权限和现有平台。

  6. Helm把 Kubernetes Manifest 组织成可版本化的 Chart。

  7. Argo CD持续比较 Git 中的期望状态与集群实际状态,并执行 GitOps Reconciliation。

流水线成功只证明自动检查覆盖的契约成立。发布还需要渐进式流量、运行指标、错误预算和回滚条件。构建一次、多环境复用同一产物,可以减少环境间不可解释的差异。

12. 韧性设计:高并发与高可用共同处理

高并发控制资源竞争,高可用控制故障影响。两者共享容量、隔离、恢复和数据一致性约束,因此放在同一个领域讨论。

先保护入口,再隔离故障

  • 令牌桶以固定速率补充令牌,允许一定突发流量;漏桶以较稳定速率排出请求,更强调平滑输出。

  • 超时限制资源占用时间,熔断在连续失败时暂时停止调用,降级返回受限能力或旧数据,排队把即时压力转为可控积压。

  • Nginx常用于 HTTP 七层代理与负载均衡,LVS/IPVS工作在四层,CDN把可缓存内容和部分安全防护前移到边缘。

排队没有消除压力,只是把压力从并发数变成等待时间和积压量。队列容量、过期时间、拒绝策略和恢复速度必须一起定义。

用目标描述高可用

主备、双活与多活描述流量和数据副本的部署方式:

  • 主备结构简单,故障时切换,重点是切换检测、RTO 和数据 RPO。

  • 双活让两个站点同时承载业务,需要处理流量分配、状态复制与冲突。

  • 多活把业务扩展到多个地域,要求数据按地域或业务单元划分,并为跨地域故障定义降级方式。

CAP 定理讨论网络分区发生时,一致性与可用性的取舍,不表示正常运行时只能任选两个字母。BASE 是工程实践中描述基本可用、软状态与最终一致性的常用概括,不是与 CAP 等价的数学定理。

Paxos 与 Raft 用于让多个节点对复制状态达成共识。ZooKeeper 与 etcd 在此基础上提供协调状态、选主、配置或租约等能力。它们不能替业务完成跨订单、库存和支付的分布式事务。

13. 分布式系统:处理跨节点状态

分布式问题通常从四类需求出现:互斥修改、跨资源事务、节点变化后的路由,以及全局标识。

分布式锁

一个可用的分布式锁需要唯一持有者标识、原子获取、有限租约、安全释放和续租边界。锁超时后,旧持有者可能继续写入,因此关键资源还需要 Fencing Token 或数据库版本检查。分布式锁减少并发,不替代幂等与数据库约束。

分布式事务

  • XA由协调者管理多个资源的准备与提交,能提供强原子性,但会延长锁持有和协调时间。

  • TCC由业务显式实现 Try、Confirm、Cancel,适合可以预留资源的短流程,开发与幂等成本较高。

  • Saga把长事务拆成多个本地事务,并为已完成步骤定义补偿,适合跨服务业务流程。补偿本身也会失败,需要持久化状态与人工处理入口。

  • Seata是分布式事务框架,提供 AT、TCC、Saga、XA 等模式。它不代表一种独立于上述模型的新事务理论。

路由与标识

一致性 Hash把节点和 Key 映射到 Hash Ring,节点变化时只迁移部分 Key;Virtual Node 用于改善分布。它适合缓存或分片路由,不能自动解决热点、数据复制与跨分片事务。

Snowflake ID通常组合时间戳、节点标识和序列号,在不访问中心数据库的情况下生成大致有序的唯一 ID。实现必须处理时钟回拨、节点 ID 冲突、同毫秒序列耗尽和信息暴露。

14. 搜索架构:词项、语义与排序

Elasticsearch 通过倒排索引把词项映射到文档,适合全文检索、过滤、聚合和相关性排序。向量检索把文本、图片或其他对象编码为 Vector,用相似度寻找语义接近的内容。

两者分别擅长不同信号:

  • 词法检索擅长产品编号、人名、错误码和精确术语。

  • 向量检索擅长同义表达、语义相近和自然语言问题。

  • Hybrid Search 组合词法与向量结果,再通过加权、RRF 或 reranker 排序。

搜索索引通常是派生数据。业务数据库保存权威事实,Outbox 或 CDC 把变化同步到索引;系统监控同步延迟、失败和数据差异,并通过 Alias 与 Reindex 完成 Mapping 演进。

向量数据库是否独立部署,取决于数据规模、过滤需求、索引算法、更新频率、延迟与团队运维能力。现有搜索引擎或关系数据库已经满足目标时,无需为了 Vector 概念增加新系统。

15. 大数据架构:批处理、流处理与湖仓表格式

技术主要职责典型用途
HadoopHDFS 分布式存储与 MapReduce 等批处理生态大规模离线存储和批量计算
Spark通用分布式计算,覆盖 Batch、SQL、Streaming 与 MLETL、交互分析、批流任务
Flink有状态流处理、Event Time、Checkpoint 与一致性状态实时指标、事件处理、持续 ETL
Hive面向数据仓库的 SQL、Metastore 与表管理离线数仓查询和数据治理入口
Iceberg开放表格式,提供 Snapshot、Schema Evolution 与 Partition Evolution多计算引擎共享数据湖表
Delta Lake开放表格式,提供事务日志、Schema Enforcement 与 Time TravelLakehouse 表与批流统一数据管理

HDFS 或对象存储负责保存文件,Spark 与 Flink 执行计算,Hive Metastore 管理元数据,Iceberg 或 Delta Lake 定义表级事务和快照。这些组件分层组合,不能用「数据湖」一个词代替所有职责。

选型要写清楚数据时效、乱序容忍、状态大小、重放方式、Schema 演进、数据质量和成本。分钟级报表不一定需要持续流处理,无法重放的数据流也无法仅靠 Checkpoint 完成灾难恢复。

16. AI 架构:知识、连接、执行与治理

AI 应用把非确定性模型放进传统软件系统后,需要额外管理 context、工具、状态、评估和成本。

能力负责的问题关键设计
RAG为本次生成检索外部证据切分、索引、Hybrid Search、reranking、引用与检索评估
MCP统一 AI Host 连接 Resources、Tools 与 Prompts 的协议认证、授权、Schema、用户确认与 Server 信任边界
Agent根据目标和执行结果动态选择下一步工具范围、步骤上限、状态、失败恢复与结果验证
Workflow用预定义步骤和分支执行稳定流程状态持久化、重试、补偿、超时与人工节点
Vector DB保存向量并执行近似相似度检索索引算法、Metadata Filter、更新与召回质量
AI Gateway统一模型入口、路由、限流、日志、成本与故障切换敏感数据、供应商差异、缓存语义和可观测性

固定流程优先使用普通代码或 Workflow。只有下一步确实依赖环境反馈、规则无法完整预写,并且结果可以验证时,Agent 才能提供相应价值。RAG 提供证据,MCP 提供连接,两者都不替代 Agent 的规划,也不要求必须引入 Agent。

评估应拆开进行:检索系统测 Recall 与排序质量,模型调用测事实一致性和结构约束,工具调用测参数与成功率,完整任务测结果是否满足验收条件。只看对话是否流畅,无法证明系统完成了工作。

17. 安全:身份、权限、传输与输入边界

身份相关概念需要准确分工:

  • OAuth 2.0是授权框架,解决 Client 如何代表 Resource Owner 获得受限访问权限。

  • OpenID Connect在 OAuth 2.0 之上增加身份认证与 ID Token。

  • JWT是一种紧凑的 Claim 表达格式,不等于登录、OAuth 2.0 或权限系统。签名、过期、Issuer、Audience、密钥轮换和撤销策略都要单独设计。

  • RBAC按角色授予权限,适合稳定职责;ABAC根据主体、资源、动作与环境属性判断,表达力更强,策略治理成本也更高。

HTTPS/TLS 保护传输中的机密性和完整性。服务端仍需校验证书、协议版本、Host、输入长度和授权上下文,敏感数据在日志、缓存、消息与备份中的保护也要单独处理。

常见 Web 攻击需要在代码边界防御:输出编码与 CSP 限制 XSS,SameSite Cookie 与 CSRF Token 防止跨站请求伪造,参数化查询防止 SQL 注入。WAF 可以拦截部分已知恶意流量和异常模式,但不能修复应用中的身份越权、业务校验和不安全查询。

安全设计从 Threat Model 开始,明确资产、信任边界、攻击面与滥用方式,再落到最小权限、Secret 管理、依赖更新、审计日志、速率限制和应急响应。

18. 可观测性:从信号还原系统行为

可观测性常用三类遥测信号:

  • Logging记录离散事件与上下文,适合查询错误细节和业务状态。

  • Metrics聚合数值与时间序列,适合趋势、容量、SLO 和告警。

  • Tracing记录请求跨服务和组件的 Span,适合定位延迟与依赖失败。

OpenTelemetry 提供生成、采集和导出 Trace、Metric 与 Log 的标准 API、SDK 和 Collector。它不负责长期存储与可视化。Prometheus 负责时间序列采集、查询和告警,Grafana 负责 Dashboard、探索和告警展示;实际系统也可以替换其中任一后端。

三类信号要通过 Trace ID、Request ID 与稳定业务标识关联。日志字段需要控制敏感数据,Metric Label 需要控制 Cardinality,Trace Sampling 需要保留错误和高延迟请求。

告警应直接对应用户影响和 SLO,例如错误率、延迟、可用性、消费积压与数据新鲜度。仅在 CPU 或内存达到固定阈值时告警,既可能漏掉业务失败,也可能制造没有行动价值的噪声。

19. 性能优化:测量运行时的真实瓶颈

性能优化从工作负载和 Profile 开始。先区分 CPU、内存分配、GC、锁竞争、网络、磁盘、数据库和下游等待,再决定修改代码、数据结构、并发模型还是基础设施。

JVM 与 Go Runtime

  • JVM 调优需要同时观察吞吐量、Tail Latency、Heap、Allocation Rate 和暂停时间。G1、ZGC 等收集器有不同目标,Heap 变大也会增加内存成本与故障恢复时间。

  • Go GMP把 Goroutine(G)调度到线程(M)上,并由 Processor(P)提供执行 Go 代码所需的调度资源。阻塞系统调用、Goroutine 泄漏、锁竞争和过量分配都可能使并发代码变慢。

  • GC 算法在吞吐、暂停、内存占用和实现复杂度之间取舍。对象生命周期与 Allocation Rate 往往比单个 GC 参数更值得先测量。

Linux I/O

  • 零拷贝减少数据在 Kernel Space 与 User Space 之间的复制或上下文切换,常见机制包括 sendfile。它是否有效取决于数据是否需要在应用层解析或修改。

  • epoll通知应用 File Descriptor 的就绪状态,适合管理大量网络连接。应用仍需正确处理 Non-blocking I/O、背压和每次读取的工作量。

  • io_uring通过 Submission Queue 与 Completion Queue 提交和完成异步 I/O,覆盖文件、网络等多类操作。它能减少部分系统调用与切换成本,但收益取决于 Kernel、驱动、工作负载与库实现。

JVM 可以使用 JFR、GC Log 和 async-profiler,Go 可以使用 pprof 与 Execution Tracer,Linux 可以使用 perf 和 eBPF 工具。优化结果必须回到同一套压测条件,对比吞吐、P95/P99 延迟、错误率、资源成本和恢复行为。

用 ADR 记录架构决策

一个架构决策可以按固定顺序写入 ADR:

  1. 记录业务目标、约束和需要改善的质量属性。

  2. 标出模块、服务、数据与信任边界,指定所有者。

  3. 比较两个或三个可行方案,写清收益、代价与拒绝原因。

  4. 定义正常请求、超时、重复、乱序、分区和恢复行为。

  5. 给出测试、指标、告警、容量和回滚条件。

  6. 约定复查时间,以及触发重新评估的流量、团队或业务变化。

延伸阅读

参考资料

架构、领域与模式

API、数据与消息

微服务、云原生与交付

分布式、搜索与数据平台

AI、安全、可观测性与性能

CO

我是 Cooper,一名生活在中国的开发者,多年来一直在家远程工作。

主要使用 Go、PHP 和 Rust,从事移动端、Web、跨境支付与资金系统开发。目前主要采用 Vibe Coding 构建产品,并以真实运行结果完成验证与交付。