从单体到云原生:一次真实后端架构演进之路
作为一名在互联网公司工作的后端开发者,我亲身经历了公司系统从最初的单体应用逐步走向微服务化、再到如今拥抱云原生的全过程。这条演进之路并不平坦,但每一步都充满了挑战与成长。
今天我想结合自己的工作经历,分享一下我们系统架构的变化过程,以及在其中遇到的实际问题和解决方案。希望这些经验能对你有所启发。
初期阶段:单体架构的美好时光

2018年刚入职的时候,公司的主业务系统还是一个典型的单体架构。整个项目代码在一个Spring Boot仓库里,前端Vue页面打包后通过Thymeleaf嵌入进去,数据库是MySQL集群,部署环境用的是阿里云ECS服务器。
当时项目的QPS大概是几百级,每天的日活用户量也不大,开发节奏很快,功能迭代一天上线几次都不成问题。
但是好景不长,随着业务快速扩张,单体应用的问题逐渐暴露出来了:
- 各个模块耦合严重,改一个接口可能牵一发动全身
- 部署慢(全量发布),出错风险大
- 性能瓶颈明显,每次促销活动时都要临时扩容ECS实例
- 技术栈单一,团队新成员上手容易,但扩展性差
记得有一次我们做了一场大促,因为一个订单服务的小bug导致整个站点全部崩溃,运维半夜紧急回滚版本,最后才恢复了正常。那次事件之后,我们开始认真思考系统的架构升级。
中期阶段:微服务拆分,迈向分布式时代

2019年开始,我们决定将系统进行微服务拆分。这是第一次架构的重大调整。
我们按照业务边界划分了几个核心微服务:
- 用户中心(user-center)
- 商品中心(product-center)
- 订单中心(order-center)
- 支付中心(payment-center)
每个服务使用 Spring Cloud + Dubbo 的方式实现 RPC 调用,注册中心用了 Nacos,网关用了 Zuul。同时引入了 RocketMQ 做异步通信解耦。
这个阶段最大的挑战来自于数据一致性问题。
举个例子,用户下单后需要调用商品库存服务减少库存,这时候一旦失败,就可能出现超卖或者数据不一致的情况。
为了解决这个问题,我们引入了 TCC 补偿事务机制,并搭建了一个简单的事务协调服务来管理分布式事务的状态流转。
// 示例:TCC 回调逻辑伪代码
public class InventoryService {
@TwoPhaseBusinessAction(name = "deductInventory")
public boolean deduct(BusinessActionContext ctx) {
// 第一阶段:预减库存
if (inventoryAvailable()) {
decreaseStockTemporarily();
return true;
}
return false;
}
@Commit
public boolean commit(BusinessActionContext ctx) {
// 第二阶段提交:实际减库存
actualDecreaseStock();
return true;
}
@Rollback
public boolean rollback(BusinessActionContext ctx) {
// 回滚:释放预扣库存
releaseTempStock();
return true;
}
}
虽然这套方案解决了当时的燃眉之急,但也带来了新的复杂度,比如事务日志的清理、补偿失败的重试策略等。
此外,随着微服务数量增多,我们的服务治理能力也面临挑战:
- 服务注册发现不稳定
- 日志追踪困难(后来引入了 SkyWalking)
- 配置管理混乱(后来迁移到 Apollo)
- 监控指标缺失(Prometheus + Grafana 上线)
那时候,我们每天都被各种“连接不上”、“超时”、“断路熔断”等问题困扰,微服务的“副作用”比我们预期的要多得多。
新的挑战:微服务维护成本高,弹性伸缩需求强烈

到了2021年,我们的微服务数量已经增长到十几个,虽然架构灵活了很多,但部署效率却下降了不少。
我们需要自己管理 Docker 容器、Kubernetes 集群资源,还要处理节点故障、负载均衡、网络隔离等问题。尤其是面对大促流量突增的时候,手动扩容显得非常低效和不可靠。
再加上我们的服务部署在北京和上海两地的 IDC 机房,跨地域调度也非常麻烦。
于是我们开始考虑向云原生方向演进。
全面上云:拥抱云原生架构
2022年,公司正式启动“全面云原生化”战略。我们将大部分服务迁移至阿里云 ACK(Kubernetes)平台,同时结合阿里云的一些托管组件,如 SLS 日志服务、ARMS 应用监控、OSS 存储服务、SLB 负载均衡等。
关键变化包括:
- 服务容器化部署(Docker + Kubernetes)
- 使用阿里云 ACK 替代自建 K8s 集群
- 数据库采用 PolarDB,读写分离自动处理
- 消息队列切换为阿里云 RocketMQ 托管版
- 引入 Serverless 函数计算处理定时任务和异步任务
我们还在每个服务中集成了 Spring Cloud Alibaba 的 Sentinel 和 Gateway,用于限流降级、灰度发布等高级控制。
这是一次真正的架构跃迁,带来的好处非常明显:
自动扩缩容能力提升
我们配置了基于 HPA 的自动扩缩容规则,当 CPU 或 QPS 超过阈值时自动加机器,大促期间也能做到秒级响应:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: order-center-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-center
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
服务治理更成熟
通过集成 Istio,我们实现了细粒度的流量治理,如金丝雀发布、A/B 测试、断路熔断等功能。
成本优化显著
相比之前自建的 K8s 集群,ACK 管理起来轻松很多。而且利用弹性容器实例(ECI),我们在非高峰期可以大量缩减资源消耗,整体云费用节省了大约 30%。
实战小插曲:一次服务雪崩事故引发的反思
有一次双十一前压测时,我们遭遇了一次严重的雪崩效应。
起因是一个第三方支付接口响应变慢,导致订单中心堆积大量请求,进而影响到了库存服务和消息队列。最终几乎所有服务都挂掉了。
这次事故让我们意识到,在微服务或云原生架构下,链式故障的影响远比单体架构要大得多。
我们采取了几项改进措施:
- 引入 Sentinel 全链路限流,限制单个服务的最大并发数。
- 增强异步化能力,将原本同步调用的关键步骤改为异步解耦。
- 建立熔断机制,服务间调用失败率超过一定阈值时自动熔断。
- 增加告警与日志分析联动,第一时间发现问题并定位。
经验总结与未来展望
经过几年的技术探索与架构演进,我有几个重要的心得体会想和大家分享:
✅ 架构不是越复杂越好
很多人以为微服务就是“先进”,但在初期业务规模不大时,单体架构反而更简单可靠。只有当系统规模达到一定程度,才值得去投入微服务的成本。
✅ 分布式事务没有银弹
从 TCC 到 Seata,我们尝试了多种方案,但每种都有其适用场景和局限性。关键是要从业务出发,尽可能避免强一致性需求,采用最终一致性的设计。
✅ 观察力比技术栈更重要
真正决定一个系统是否稳定、可维护的,不只是你用了多少“高大上”的框架,而是你是否有足够的监控、日志、告警和链路追踪手段。
我们现在已经全面接入了 APM 工具(SkyWalking + ARMS),每当接口出现延迟时,都能迅速定位到具体链路上哪个环节出问题。
✅ 云原生是未来趋势
随着 CNCF 生态的不断成熟,越来越多的企业正在从自建架构转向云原生体系。如果你还没接触过 Kubernetes、Service Mesh、Serverless 等技术,建议尽快上手学习。
写在最后
技术的道路从来都不是一条直线,它更像是螺旋上升的过程。每一次架构的变迁,背后都是一个个真实的需求推动出来的,而我们也正是在这种“痛并快乐着”的过程中,不断成长。
希望通过这篇文章,能够让你更清晰地看到一个后端服务是如何一步步从单体走向云原生的,也希望你能在自己的项目中少踩一些坑。
如果你也有类似的架构演进经验,欢迎留言交流,我们一起进步 💪
📌 作者:一位不愿透露姓名的老码农
🧩 技术栈:Java / Spring Boot / Spring Cloud / Kubernetes / CNCF

评论 0