别再为选框架纠结了,先把这 7 个架构模式吃透

软件架构没有万能银弹,但有一套实用的模式组合,可以在复杂业务、快速迭代和团队协作之间找到平衡。本文用通俗的方式拆解 7 个常见架构模式,并展示它们如何在同一个电商系统里协同工作。

架构不是炫技,而是用尽量简单、可演进的方式,解决当下最关键的问题。

软件架构没有标准答案,不同业务、团队规模和技术栈,往往需要完全不同的方案。但有一点是共通的:优秀的架构师往往不会从"框架选型"开始,而是从"模式组合"开始

这篇文章结合实际经验,聊聊几个在真实项目中非常实用的架构模式:

  • 有助于拆分复杂业务的 有界上下文(Bounded Contexts)
  • 给旧系统"挂外挂"的 边车模式(Sidecar)
  • 异步解耦的 发布-订阅(Publisher-Subscriber)
  • 统一入口的 应用网关(Application Gateway)
  • 大家谈之色变却又离不开的 微服务(Microservices)
  • 拆分前端的 微前端(Microfrontends)
  • 在读写上动刀的 CQRS 与事件溯源(Event Sourcing)
  • 最后,把它们组合在一起的 多样化架构(Polyglot Architecture)

不必一次性全用上,但理解它们适合解决什么问题,会极大提升你的架构判断力。


1. 有界上下文:从"一个系统"到"若干清晰的小世界"

很多项目一开始只有一个"单体应用":单一代码仓库、单一数据库,所有领域概念搅在一起。时间一长,你会发现:

  • 同一个词在不同模块中含义不一样(比如「订单」在风控、结算、客服里的含义都不同)
  • 改一个小需求,要改一大堆看不懂的代码
  • 想拆服务,却不知道从哪里下手

有界上下文(Bounded Context) 就是用来给这些概念设定"边界"的:

  • 每个上下文只关心一小块业务,例如:商品目录、下单流程、支付、账号与权限等
  • 每个上下文内部,术语、数据结构和业务规则是统一的
  • 上下文与上下文之间,通过明确的接口或消息进行沟通

在代码组织层面,可以这样落地:

  • 以业务上下文为维度拆分目录结构、模块或服务
  • 每个上下文内有自己的领域模型、用例、基础设施
  • 未来如果要做微服务或模块化,只需顺着这些上下文天然拆分

适用场景:

  • 业务复杂度中高、概念众多的系统(例如电商、金融、SaaS 平台)
  • 已经感觉到"牵一发而动全身",但还没正式上微服务
  • 想给未来的服务拆分、团队拆分铺路

2. 边车模式(Sidecar):不给旧系统做大手术的外挂方案

现实世界里,大量核心系统是旧的:

  • 技术栈陈旧,不好改
  • 稳定运行多年,没人敢动
  • 但又需要增加鉴权、日志、监控、限流等横切能力

边车模式(Sidecar) 的做法是:在主应用旁边,部署一个"伴生进程",统一接管进出流量或公共能力:

  • 所有流量先经过 Sidecar,再转发到主应用
  • Sidecar 里实现认证、授权、访问控制、日志、熔断、重试、限流等功能
  • 主应用基本不需要改动,就能享受一整套通用能力

在 Kubernetes 世界里,Service Mesh(服务网格) 就是把 Sidecar 发挥到极致:

  • 每个 Pod 里都有一个代理 Sidecar
  • 所有服务间通信都走 Sidecar,方便统一加密、监控、限流

适用场景:

  • 无法轻易修改的遗留系统,需要补齐安全或观测能力
  • 希望在多语言、多技术栈的服务之间,统一实现横切逻辑

3. 发布-订阅:用消息中间件解耦系统

当系统之间存在大量"谁调用谁"的同步 HTTP 调用时:

  • 上游挂了,下游全挂
  • 扩容、限流、熔断都变得很复杂

发布-订阅(Publisher-Subscriber) 模式通过消息中间件,把发送者和接收者解耦:

  • 发布者(Publisher) 只负责往 Topic 里发消息,不关心具体是谁在消费
  • 订阅者(Subscriber) 只负责订阅感兴趣的 Topic,异步处理消息

常见有两种投递机制:

  • 竞争消费者(Competing Consumers):一条消息只会被某个订阅组里的一个消费者处理,适合将耗时任务并行分摊给多台 Worker
  • 广播 / 扇出(Fanout):同一条消息会被多个订阅者分别消费,适合同步事件到多个下游系统

适用场景:

  • 需要异步处理的长耗时任务(例如生成报表、发送邮件 / 短信)
  • 一个业务事件需要通知多个下游(例如订单已支付,需要通知库存、物流、营销等)
  • 希望系统间解耦,提升整体容错能力

4. 应用网关:给复杂后端的统一"门面"

当后端服务越来越多时,如果每个服务都直接对外暴露:

  • 前端要记很多不同的域名和端口
  • 统一的鉴权、限流、防火墙配置都很麻烦

应用网关(Application Gateway) 提供了一个统一入口:

  • 客户端只访问一个域名,例如 api.example.com
  • 网关根据路径前缀、Host、Header 等信息,把请求路由到具体的后端服务
  • 同时在网关层统一处理 SSL 终止、WAF、防爬、限流、黑白名单、统一鉴权等

和传统的四层负载均衡相比,应用网关工作在七层(HTTP 协议级别),可以做"看得懂业务"的路由与策略。

适用场景:

  • 需要在一个或少量域名后面,承载大量后端服务
  • 希望统一处理安全策略、流量治理、监控统计

5. 微服务:拆还是不拆,这是个问题

微服务(Microservices) 是把一个应用拆成一组小而独立的服务:

  • 每个服务有自己的 API 和数据库
  • 服务之间通过网络协议交互,可以独立部署、独立扩缩容
  • 可以选择不同的技术栈与存储方案

听上去很美,但实践中踩坑无数:

  • 分布式事务、数据一致性更难
  • 调试和排错成本大幅上升
  • 部署、监控、配置管理复杂度飙升

因此,微服务更像是一组架构 trade-off 的打包选择

  • 用更高的运维复杂度,换取更好的团队并行开发、独立部署、可扩展性

适用场景(真的需要时):

  • 不同业务模块对性能、扩展性、高可用有明显不同要求
  • 不同团队需要相对独立的迭代各自的模块
  • 已有清晰的有界上下文划分和较成熟的 DevOps 体系

如果应用还不复杂、团队不大,一个结构清晰的单体 + 有界上下文 + 模块化,往往比微服务更务实。


6. 微前端:把"大前端"拆给不同团队

在微服务火了之后,很多团队发现前端也遇到了类似问题:

  • 单一前端工程越来越大,构建、发布越来越慢
  • 多个团队改同一个仓库,冲突频发
  • 不同页面由不同团队维护,生命周期不一致

微前端(Microfrontends) 的想法是:

  • 把一个 Web 前端拆成多个独立的前端"小应用"
  • 每个小应用负责一块功能区域,有自己的发布节奏
  • 再通过 Portal 或壳应用把它们拼接在一起

随着 Web Components 等标准成熟,不同微前端甚至可以使用不同框架,只要最终暴露为统一的组件接口即可。

适用场景:

  • 大型 Web 应用,需要由多个团队长期维护不同功能区
  • 希望不同业务模块可以独立发布、独立回滚
  • 前端代码规模快速增长,单仓库已难以维护

7. CQRS 与事件溯源:为性能和审计而"分家"

在很多系统中,读请求远多于写请求,或者读写对数据的关注点完全不同。

CQRS(Command Query Responsibility Segregation,命令查询职责分离) 提出:

  • 写入(命令)和读取(查询)使用不同模型甚至不同数据存储
  • 写端专注于正确性、业务规则、事务一致性
  • 读端专注于查询效率、报表需求和多维视图

在更极端的版本里,会配合 事件溯源(Event Sourcing)

  • 写端不直接存"当前状态",而是存一串不可变事件(例如账户"存入 100""支出 30")
  • 需要当前状态时,通过回放这些事件来"还原"
  • 任意时刻都可以重建不同视图,天然具备强审计能力

适用场景:

  • 对性能、可扩展性、审计追踪有极高要求的系统(比如支付、风控)
  • 读写模型截然不同、读远大于写的业务

需要注意的是:CQRS + 事件溯源的学习和维护成本极高,没有足够收益时不要轻易上。


8. 多样化架构:在同一个系统里"拼装"模式

在一个真实的电商系统中,上面这些模式往往是组合使用的,而不是"择一而用":

  • 有界上下文 拆出商品、订单、支付、账号等领域
  • 每个上下文内部,可以选择是否做 微服务 拆分
  • 前端用 微前端 把不同业务团队维护的页面拼在一起
  • 跨上下文的事件同步,用 发布-订阅 和消息中间件来解耦
  • 对外只暴露一个域名,由 应用网关 把请求路由到不同后端
  • 在关键核心链路上,用 CQRS / 事件溯源 保证审计与可追溯
  • 对老系统或第三方服务,用 Sidecar 补上安全与观测

这类组合式方案,可以称为 多样化架构(Polyglot Architecture)

  • 不执着于某一种"统一架构风格"
  • 而是根据每个有界上下文的特性,选择最合适的模式与技术栈

写在最后:别为模式而模式

在架构设计时,可以反向问自己三个问题:

  1. 这块业务目前最大的痛点是什么?是复杂度、性能、可用性,还是团队协作?
  2. 现有架构哪里已经明显"不够用了"?
  3. 如果引入一种模式,能具体缓解哪些问题,同时又会增加哪些新的复杂度?

理解模式,是为了在关键决策点有更多可用的"工具",而不是为了把系统堆成「炫技合集」。永远从问题出发,再选择最简单可行的模式组合,这也许就是架构这门"艺术"的核心。


Hi,我是俞凡,一名兼具技术深度与管理视野的技术管理者。曾就职于 Motorola,现任职于 Mavenir,多年带领技术团队,聚焦后端架构与云原生,持续关注 AI 等前沿方向,也关注人的成长,笃信持续学习的力量。在这里,我会分享技术实践与思考。欢迎关注公众号「DeepNoMind」,星标不迷路。也欢迎访问独立站 www.DeepNoMind.com,一起交流成长。

相关推荐
七夜zippoe2 小时前
Python性能分析实战:从cProfile到火焰图,精准定位性能瓶颈
python·架构·内存泄漏·火焰图·cprofile
Amos_Web2 小时前
Rust实战(五):用户埋点数据分析(前)
后端·架构·rust
Aaron15882 小时前
基于RFSOC 49DR+VU13P的64通道VPX架构波束成形技术分析
c语言·人工智能·算法·架构·信息与通信·信号处理·基带工程
岁岁种桃花儿2 小时前
从响应头拆解大厂静态资源部署架构:Tengine+OSS+CDN核心逻辑
运维·http·架构
鲨莎分不晴2 小时前
云计算技术架构与原理深度解析:从虚拟化到云原生的演进之路
云原生·架构·云计算
恭仔さん3 小时前
大模型推理架构 TGI vs vLLM
架构·vllm·tgi
乾元3 小时前
专栏案例合集:AI 网络工程交付的完整闭环—— 从 Demo 到 Production 的工程化方法论
运维·开发语言·网络·人工智能·架构·自动化
狮子座明仔12 小时前
Engram:DeepSeek提出条件记忆模块,“查算分离“架构开启LLM稀疏性新维度
人工智能·深度学习·语言模型·自然语言处理·架构·记忆