从单体到云原生:我在一家中型电商的五年架构演进实录
去年双11凌晨三点,我蹲在公司茶水间啃着冷掉的汉堡,盯着监控面板上那个不断飙升的CPU曲线,心里只有一个念头:这破系统再撑不住,我就辞职去开滴滴。
彼时我刚晋升技术组长没多久,手下带着三个新人,而我们负责的订单服务正卡在单体架构的泥潭里动弹不得——数据库连接池爆了,接口响应时间飙到5秒+,运维同事在群里疯狂@我:“你这服务再不扩容,明天就别来了!”
说来惭愧,五年前我刚入职这家公司时,后端就一个Spring Boot单体应用,前端Vue搭个管理后台,数据库MySQL一主两从,部署在三台物理机上。简单、粗暴、但能跑。产品经理每次提需求都像在点外卖:“加个优惠券叠加逻辑,周三上线哈。” 我们当时还真信了,结果上线当天直接OOM,半夜被PagerDuty叫醒,重启服务时手都在抖。
如今回头看,那段“单体岁月”虽然痛苦,却也让我深刻理解了什么叫“技术债滚雪球”。所以今天这篇,不讲大道理,就聊聊我们团队这五年怎么一步步从“单体泥潭”爬出来,最终拥抱云原生的实战过程。顺便,也给正在准备跳槽刷题的兄弟们一点参考——毕竟现在面试官张口闭口都是“微服务治理”“Service Mesh”,你要是只会写CRUD,简历怕是过不了HR那关。
单体时代:看似美好,实则埋雷
2019年,我们的系统还是典型的“大泥球”架构:用户、商品、订单、支付、库存全塞在一个代码库里,Maven模块倒是分了十几个,但启动时一个JVM进程扛所有。本地开发倒是快,./mvnw spring-boot:run 三十秒搞定,但一旦上线,问题就来了。
最典型的是数据库耦合。订单表和用户表在同一个库,促销活动一搞,用户服务疯狂查用户等级,订单服务又在写流水,结果死锁频发。有一次大促,DBA凌晨给我打电话:“你这事务隔离级别设成READ_COMMITTED了?赶紧改回REPEATABLE_READ,不然主库要挂!” 我当时一脸懵,后来才意识到,单体架构下,一个模块的SQL优化可能直接影响另一个模块的稳定性。
更头疼的是部署粒度。想改个商品详情页的缓存策略?得整个应用重新打包、测试、上线。有次为了修复一个日志格式的小bug,结果因为测试覆盖不全,把支付回调逻辑搞崩了,被老板当面训了半小时。那会儿我常自嘲:“我们不是在写代码,是在玩俄罗斯套娃,改一层,崩三层。”
第一次拆分:微服务初体验,坑比想象中多
2021年,公司融了B轮,老板拍板:“搞微服务!对标阿里!” 于是我们开始了第一次架构拆分。目标很明确:把订单、用户、商品拆成独立服务,用Dubbo做RPC,Nacos做注册中心,Redis缓存热点数据。
听起来很美好,对吧?实际操作起来差点把我送走。
第一个坑是分布式事务。用户下单要扣库存、生成订单、发优惠券,三个服务各干各的,怎么保证一致性?我们一开始用TCC(Try-Confirm-Cancel),结果发现补偿逻辑写得比业务还复杂。有一次网络抖动,Confirm阶段失败,用户钱付了但订单没生成,客服电话被打爆。最后不得不引入RocketMQ事务消息,靠“本地事务表 + 消息重试”兜底,代码量翻倍,但至少稳住了。
第二个坑是服务依赖地狱。订单服务调用户服务,用户服务又调积分服务,链路一长,一个慢查询就能拖垮整个链路。有次商品服务GC停顿2秒,导致订单创建超时,下游支付超时,最后用户投诉“付了钱没下单”。我们紧急上了Sentinel做熔断降级,配置规则时手都在抖——阈值设高了没用,设低了误杀正常请求。
# sentinel规则示例(当时熬夜调出来的)
resource: com.order.service.createOrder
count: 1000 # QPS阈值
grade: 1 # QPS模式
controlBehavior: 0 # 快速失败
说实话,那段时间我天天在想:微服务是不是个骗局?直到某天参加QCon技术大会,听一位老哥吐槽:“微服务不是银弹,但单体是慢性毒药。” 才明白,问题不在架构本身,而在我们太急于求成,忽略了配套能力建设。
云原生入局:K8s + Service Mesh 的救赎
2023年初,公司决定全面上云。这次我们学乖了:先建基础设施,再迁业务。核心思路就一条——让基础设施接管复杂性,让开发者专注业务。
我们选了阿里云ACK(Kubernetes托管集群)作为底座,Istio做Service Mesh。迁移过程堪称“刮骨疗毒”:
- 容器化改造:把每个微服务打成Docker镜像,用Helm管理部署。以前部署靠运维手动scp jar包,现在一条
helm upgrade搞定。 - 服务网格接入:通过Sidecar代理处理服务间通信,熔断、限流、重试全由Istio控制平面配置,业务代码零侵入。
- 可观测性升级:Prometheus + Grafana监控指标,Jaeger追踪链路,ELK收集日志。终于不用再SSH进机器tail -f看日志了!
举个具体例子:订单服务调用库存服务,以前要在代码里写熔断逻辑,现在只需在Istio VirtualService里配几行YAML:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: inventory-service
spec:
hosts:
- inventory-svc
http:
- route:
- destination:
host: inventory-svc
retries:
attempts: 3
perTryTimeout: 2s
timeout: 5s
效果立竿见影。今年618大促,库存服务因数据库慢查询响应变慢,Istio自动重试+超时熔断,订单服务毫发无损。我在监控大屏前喝着咖啡,心想:这钱花得值。
Function Calling 与 ChatGPT:新工具如何改变架构思维
最近我在刷LeetCode准备跳槽(没错,晋升后反而更焦虑了),偶然发现一个有趣现象:现在的面试题越来越关注“系统设计”,而不仅是算法。比如“设计一个短链服务”、“实现一个分布式ID生成器”。这时候,ChatGPT + Function Calling 成了我的秘密武器。
别误会,我不是让AI写代码。而是用它快速验证架构思路。比如上周,我想设计一个异步任务调度系统,就在ChatGPT里描述需求:
“我需要一个支持定时触发、失败重试、优先级队列的任务系统,用Redis做存储,Java实现。请给出核心数据结构和状态机设计。”
它不仅能列出任务表字段(task_id, cron_expr, status, retry_count...),还能通过Function Calling调用我预设的“架构评估函数”,返回类似这样的建议:
{
"recommendation": "使用Redis Streams代替List,避免消费者丢失消息",
"pitfall": "注意时钟漂移问题,建议用UTC时间戳",
"scaling_tip": "可按task_type分片,提高并发处理能力"
}
这种“人机协作”模式,极大提升了我的设计效率。更重要的是,它让我意识到:未来的架构师,不仅要懂技术,更要会用工具放大自己的认知边界。就像当年我们从手动部署转向CI/CD一样,工具进化永远在推动架构演进。
架构演进中的血泪教训
回顾这五年,踩过的坑比写的代码还多。分享几个关键心得:
1. 不要为了拆而拆
微服务不是目的,解耦才是。如果两个模块变更频率极低、强一致性要求高,硬拆反而增加复杂度。我们现在有个“服务合并评审会”,拆之前先问:这个服务未来一年会独立迭代吗?
2. 数据库拆分比服务拆分更关键
我们曾以为服务拆了就完事,结果发现数据库还是单点瓶颈。后来采用“垂直分库 + 水平分表”策略:
- 用户库、订单库、商品库物理分离
- 订单表按user_id哈希分16张表
- 用ShardingSphere-JDBC做透明路由
| 拆分维度 | 工具选型 | 踩坑点 |
|---|---|---|
| 垂直分库 | 自研路由中间件 | 跨库事务难处理 |
| 水平分表 | ShardingSphere | 分页查询性能差 |
| 读写分离 | MyCat | 主从延迟导致脏读 |
3. 云原生不是终点,而是新起点
上了K8s后,我们以为万事大吉,结果发现新问题:Pod频繁重启、HPA扩缩容滞后、ConfigMap更新不生效... 这才明白,云原生的核心不是技术堆砌,而是自动化 + 自愈能力。现在我们的SRE团队每天干的事,就是写Operator和自定义Controller。
给准备跳槽的同行一点建议
作为过来人,真心建议:如果你想在求职中脱颖而出,光会调API远远不够。面试官真正想考察的是你在复杂约束下的权衡能力。
比如被问到“为什么选Kafka而不是RabbitMQ?”,别说“Kafka吞吐高”这种废话。应该结合场景:“我们订单流水需要持久化7天+高吞吐写入,Kafka的分区日志和批量刷盘更适合;而通知类消息用RabbitMQ的Exchange路由更灵活。”
另外,多参与开源或技术社区。我去年在GitHub上贡献了一个Istio配置校验工具,结果被某大厂面试官看到,直接问:“你这个PR里提到的sidecar注入问题,线上怎么解决的?” 聊了半小时,offer基本稳了。
写在最后
从单体到云原生,本质上是一场“复杂度转移”:把业务复杂度,转化为基础设施复杂度。作为开发者,我们要做的不是消灭复杂度,而是在合适的抽象层级上管理它。
上周五晚上,我又加班到十点,但心情完全不同。看着K8s Dashboard上自动扩缩容的Pod曲线,突然觉得:这五年折腾,值了。
至于跳槽?嗯,简历已经投出去了。但不管去哪儿,我都带着一个信念:好的架构,应该让写代码的人睡得着觉。
(完)
P.S. 如果你也在经历架构转型,欢迎留言交流。或者,如果你司缺个懂云原生的前端转后端(别笑,我真这么干过),简历砸过来?😉

评论 0