后端架构演进:从单体到云原生 —— 一位老后端的自白

代码轻食主义
2025-06-17 07:21
阅读 666

引言:我的“架构进化”之路

引言:我的“架构进化”之路

记得三年前,我在一个创业团队里担任后端技术负责人。我们当时开发的是一个电商类 SaaS 平台,面向中小型商户提供线上店铺管理服务。起初项目规模不大,只有三个人的小团队,为了快速上线,我们采用了一个标准的 Spring Boot 单体架构,前后端分离,数据库是 MySQL。

刚开始一切都好,部署简单、调试方便。但随着功能越来越多,系统越来越臃肿,运维成本越来越高,代码质量也在不知不觉中开始滑坡。

直到某个黑五促销期间,一场“灾难”悄然降临……


问题描述:单体架构的瓶颈逐渐显现

问题描述:单体架构的瓶颈逐渐显现

那次活动当天,用户下单量陡增 5 倍。我们信心满满地准备了弹性扩容方案,结果悲剧发生了:

  • 服务崩溃:订单模块和支付模块同时出问题,导致整个应用宕机。
  • 数据库连接池被打满:多个业务模块共用同一个数据库连接池,相互影响严重。
  • 发布风险大:一次小改动就要全量重新部署,一不小心就会拖累其他模块。
  • 性能难调优:不同模块混在一起,资源利用率混乱,排查性能瓶颈极其困难。

当时的我,第一次感受到“架构设计”的重要性远远超出了“写好代码”。

那段时间,我和团队天天加班排雷,凌晨两三点还在查线程堆栈、看监控图表。虽然最后挺过去了,但也让我意识到:是时候重构我们的架构体系了


解决方案:架构拆分与微服务落地实践

解决方案:架构拆分与微服务落地实践

Step 1:从单一模块抽离核心服务

我们第一步不是直接上微服务,而是做了两件事情:

  1. 识别高频率调用模块:比如用户鉴权、订单处理、支付、库存等。
  2. 将这些模块抽成内部 jar 包/子模块(Spring Boot 多模块项目),实现初步解耦。

这样做的好处很明显:

  • 各个模块职责清晰
  • 可独立测试
  • 为后续拆成独立服务打下基础

举个例子,我们将用户鉴权抽象为 auth-service-core,供主应用和其他未来服务引用。

Step 2:走向真正的微服务架构

当核心模块已经完成内聚之后,我们决定正式迈出第二步:引入 Spring Cloud + Dubbo 构建微服务架构。

技术选型回顾:

组件 技术选型
注册中心 Nacos
配置中心 Spring Cloud Config + Git
网关 Spring Cloud Gateway
通信协议 REST / Dubbo RPC
服务治理 Sentinel
日志追踪 SkyWalking

拆分过程中的几个关键决策:

  1. 服务粒度控制得当
    初期有人主张彻底细分每一个接口为一个服务,但我们坚持“业务边界优先”的原则,以高内聚低耦合为目标,最终划分了以下几个服务:

    • 订单中心 Order Center
    • 用户中心 User Center
    • 商品中心 Product Center
    • 支付中心 Payment Center
    • 库存中心 Inventory Center
    • 通知中心 Notification Center
  2. 数据库垂直拆分
    每个服务配备专属数据库实例,使用 MyCat 分表分库。虽然初期带来一定维护复杂度,但从长远来看非常值得。

  3. 统一网关设计
    我们没有直接暴露服务,所有请求都走统一 API 网关,做统一鉴权、限流、日志记录,极大提升了安全性和可观测性。

  4. 灰度发布 & 流量回放机制
    在部署时,我们实现了基于请求 header 的灰度规则,并在压测时借助“流量录制工具”,对生产环境的请求进行复现分析。

这一阶段完成后,系统的稳定性有了明显提升,特别是高并发场景下的抗压能力显著增强


进一步升级:拥抱云原生生态

进一步升级:拥抱云原生生态

随着时间推移,我们的服务节点数量持续增长,手动部署和维护成本逐渐攀升。于是,我们迈出了第三步:全面拥抱云原生技术。

我们选择了 AWS 和 Kubernetes 生态作为主要平台,并进行了以下改造:

1. 容器化部署 & 编排升级

  • 所有服务 Docker 化,通过 CI/CD 自动打包镜像
  • 使用 Helm Chart 管理服务配置,便于多环境部署
  • 引入 Kubernetes 做集群编排,结合 HPA 实现自动扩缩容

小插曲:刚上 Kubernetes 的时候,我们没给 Pod 设置内存限制,结果一个服务吃爆整个节点,还搞挂了 Redis。从此以后,我们严格执行 resource quota 限制。

2. 微服务治理能力再提升

  • 使用 Istio 替换部分 Sentinel 能力,更精细地控制服务间通信
  • 使用 Prometheus + Grafana 实现可视化监控报警
  • 使用 Loki 收集容器日志,替换 ELK 方案(轻量高效)

3. 数据库进一步演进

  • 将部分非强一致性场景改为使用 MongoDB,应对文档类数据需求
  • 引入 Redis Cluster 作为缓存加速层
  • 对热点数据进行读写分离 + 分片存储

4. Serverless 探索

我们在非关键路径上试用了 AWS Lambda 来处理一些异步任务,比如生成报表、短信推送等,效果不错。

  • 成本降低:按需计费,节省了不少空闲资源开销
  • 开发效率提升:无需关注部署细节,逻辑即服务

效果总结:稳定性、扩展性、可维护性全面提升

经历了这一系列架构演进后,我们的系统整体表现可以用三个词概括:稳定、灵活、智能

具体来说:

指标 演进前 演进后
部署耗时 >20分钟/次 <3分钟
故障隔离能力 全局影响 服务级隔离
QPS 承载能力 3k 18k+
错误率 0.5%左右 <0.05%
运维人力投入 2人/周 0.5人/周
新业务接入时间 2~3周 3~5天

API接口文档-1

特别是去年双十一大促期间,系统扛住了近百万 PV 的访问压力,且没有发生一起重大故障。

最让我欣慰的是,团队成员也能更专注于各自负责的模块,而不是天天救火。


经验分享:给后端兄弟们的几点建议

缓存策略对比-2

作为一名“走过弯路”的老后端,我有一些心得想分享给大家:

✅ 架构设计永远是业务先行

不要为了微服务而微服务,要从业务实际出发,判断是否真的需要拆分。有时候一个结构良好、组件明确的单体系统比一堆杂乱无章的微服务更靠谱。

✅ 技术债是慢慢积累的

很多系统变慢、不稳定的背后,其实是架构不合理叠加代码坏味道的结果。定期重构是必须的,越早越好。

✅ 监控是救命稻草

别只顾着写代码,一定要尽早搭起监控体系。Prometheus + Grafana 是个很好的起点,SkyWalking、ELK、Loki 也可以根据项目规模逐步引入。

✅ 自动化部署不能省

CI/CD 不只是运维的事,它直接影响研发交付效率。Jenkins、GitLab CI、Argo CD 都可以试试,关键是打通全流程。

✅ 团队协作要跟上节奏

架构演进了,流程也要跟着改。我们后来制定了统一的服务命名规范、接口文档标准、错误码机制,才真正把协同效率拉上去。


写在最后:云原生不是终点,而是新的起点

回头看这几年,从单体到微服务再到云原生,每一步都在解决旧问题的同时带来了新挑战。但正是这种不断的迭代与优化,让我们能适应更高的业务需求和更复杂的用户场景。

如果你现在正面临类似的转型困惑,不妨问问自己这三个问题:

  1. 你的系统是否有明确的业务边界?
  2. 当前的技术栈是否能够支撑未来的扩展?
  3. 团队是否有能力驾驭更复杂的架构模式?

记住一句话:“没有银弹,只有不断演进的架构。

愿你在技术进化的路上少走弯路,走得更远。


文章作者:一位深耕 Java 后端多年的老程序员,现就职于一家头部跨境电商平台负责核心系统架构设计。热爱开源,曾主导多个大型分布式系统的设计与落地。欢迎交流:hello@codearchitect.com

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝