微服务架构设计实战:从单体到分布式——一个被裁全栈的血泪转型路
去年十月的一个雨夜,我坐在杭州文一西路那间不到60平的小房子里,盯着电脑屏幕上“公司组织架构优化”的邮件发呆。那天是周三,窗外的雨下得特别大,滴滴答答打在阳台的遮雨棚上,像是在给我敲丧钟。
HR说得挺委婉:“感谢你过去两年的贡献……当前业务聚焦核心方向……N+1补偿已打款。”
我点开银行APP,看到账户里多了一笔38,200元。算下来,月薪15k,工作26个月,N+1刚好这个数。不多不少,像极了我这三年的职业生涯——不温不火,却也足够让我背上每个月4300块的房贷。
老婆当时在厨房煮面,没说话,只是轻轻把一碗热腾腾的阳春面放在我桌上,汤面上飘着两片青菜和一个煎蛋。“吃吧,明天再想。”她说。
可哪有“明天”?房贷不会等我,生活也不会。
单体时代的“万能胶水”
被裁前,我在一家做本地生活SaaS的公司当全栈开发。说是全栈,其实就是“背锅侠”:前端Vue写页面,后端Java搭接口,数据库慢了调索引,服务器崩了半夜爬起来重启——连爬虫模块都是我顺手加的。
我们的系统是个典型的单体应用:一个Spring Boot项目,前端用Vue2,数据库MySQL + Redis缓存,部署在阿里云ECS上。功能说复杂也不复杂:商家后台、用户小程序、运营数据看板、还有个用来抓竞品价格的Python爬虫模块(对,就是那个半夜被反爬封IP、还得手动换代理的玩意儿)。
但问题在于,所有东西都塞在一个仓库里。
- 运营同事要改个促销Banner?得我改代码、提MR、测试、上线。
- 前端想换个UI组件?得等后端接口联调完。
- 爬虫跑崩了?整个服务502,用户打不开小程序。
最夸张的一次是去年618,运营搞了个“满199减50”的活动,结果因为爬虫模块内存泄漏,把整个JVM搞崩了。凌晨两点,我在床上被钉钉报警吵醒,爬起来SSH登录服务器,kill -9 之后瘫在椅子上,心想:这破系统,迟早把我送走。
可那时候不敢动架构。老板说:“能跑就行,别折腾。” 技术债像滚雪球,越积越大。
外包接单,被迫成长
被裁后第三天,我开始在电鸭、程序员客栈、甚至闲鱼上挂“全栈开发接单”。
第一单是个做宠物电商的小老板,需求很简单:做个微信小程序,支持商品展示、下单、支付,后台能管理订单和库存。报价5000,工期两周。
我信心满满地用老套路搭:Vue3 + Spring Boot + MyBatis,数据库还是MySQL。
结果做到一半,客户突然说:“能不能加个功能?每天自动抓淘宝上同款宠物粮的价格,低于我们售价就发提醒。”
我内心OS:又来爬虫?!
但为了5000块,咬牙上了。用Scrapy写了爬虫脚本,部署在同一台服务器上。结果三天后,爬虫触发淘宝风控,IP被封,连带小程序访问也变慢——因为共用同一个出口IP和带宽资源。
客户急得打电话:“兄弟,我这边用户投诉打不开,怎么回事啊?”
我支支吾吾解释不清,最后只能自掏腰包买了个代理IP池,临时救场。那单做完,利润只剩2800块,还搭上了三个通宵。
那一刻我意识到:单体架构,在外包这种“小快灵”的场景里,简直是自缚手脚。
转折点:微服务不是选择,是生存
今年春节前,一个老同事介绍我接了个大活:帮一家做社区团购的创业公司重构系统。预算8万,周期两个月。对方CTO很直接:“我们现在系统一到晚上七点就卡死,运营没法上新商品,团长没法下单,再这样下去,公司撑不过Q2。”
我去看他们的代码,熟悉的配方:单体Spring Boot,爬虫、订单、用户、库存、运营活动全挤在一起。日活3万,峰值QPS 1200,数据库CPU常年90%以上。
“能不能拆?”我问。
“能!但没人敢动,怕拆散了更完蛋。”CTO苦笑。
回家路上,我在地铁上刷知乎,看到一篇《微服务不是银弹,但可能是救命稻草》。突然想到:我已经被裁了,还有什么好怕的?大不了再接几单爬虫糊口。
于是咬牙接下这单,并提出架构改造方案:拆成五个微服务:
- 用户服务(User Service):管注册、登录、权限
- 商品服务(Product Service):商品信息、分类、库存
- 订单服务(Order Service):下单、支付、状态流转
- 运营服务(Campaign Service):促销活动、优惠券、Banner配置
- 数据采集服务(Crawler Service):独立爬虫模块,只负责抓数据,不参与核心链路
每个服务独立部署,用Docker容器化,通过Nginx + Gateway路由,数据库也按领域拆分(用户库、商品库、订单库),Redis集群做缓存,RabbitMQ解耦异步任务。
最关键的是——爬虫彻底剥离!它不再和主业务共享资源,即使被封IP、内存爆掉,也只影响数据采集,不影响用户下单。
实战细节:那些踩过的坑
1. 前端如何对接多个服务?
以前单体时代,前端只要配一个baseURL。现在五个服务,五个域名?太乱。
解决方案:API网关统一入口。
我用Spring Cloud Gateway做了路由聚合:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/product/**
前端依然只调https://api.xxx.com,网关内部转发。运维成本低,前端无感。
2. 运营要改Banner,还要找我?
运营服务独立后,我把Banner、活动配置做成可视化后台,运营自己就能改。
技术上用了动态配置中心(Nacos Config),改完实时生效,不用重启服务。
运营小姐姐第一次自己改完Banner,兴奋地在群里@我:“哥!我搞定了!” —— 那一刻,我觉得值了。
3. 爬虫资源隔离
Crawler Service单独部署在一台低配ECS(2核4G,月付89块),用Celery + Redis做任务队列。
每次抓取任务由运营服务触发(比如“监控A商品价格”),Crawler抓完存入独立数据库,再通过MQ通知商品服务更新比价字段。
资源隔离 + 异步通信 = 核心链路稳如狗。
4. 分布式事务怎么办?
用户下单涉及扣库存、生成订单、发优惠券。
我没上Seata那种重型方案,而是用最终一致性 + 补偿机制:
- 先扣库存(成功才继续)
- 创建订单(本地事务)
- 发MQ消息给优惠券服务
- 如果优惠券失败,定时任务扫描“未发券订单”,重试三次,还不行就人工介入
简单,但够用。毕竟创业公司,先跑起来再说。
成本与收益:真实账本
有人问:“微服务不是更贵吗?”
确实。以前1台4核8G ECS(月付300块)搞定一切。现在:
- 网关 + 注册中心:1台
- 用户/商品/订单服务:各1台(高可用至少2副本)
- Crawler服务:1台
- Redis集群:3节点
- RabbitMQ:2节点
- MySQL分库:3实例
月成本涨到2200左右。但客户愿意付——因为系统稳定了,晚上七点高峰不再崩,团长能正常下单,GMV涨了30%。他们说:“这钱花得值。”
而我呢?这单收了8万,刨去服务器成本、加班咖啡、老婆抱怨的时间成本,净赚6万出头。比上班时两个月工资还多。
更重要的是——我学会了真正的分布式架构落地能力。不再是PPT架构师,而是能在资源有限、时间紧迫、客户催命的情况下,把微服务跑起来的人。
给同行的建议:别为了微服务而微服务
写到这里,我想说句掏心窝的话:微服务不是万能药,单体也不是原罪。
如果你的系统日活不到1万,团队不到5人,别急着拆。先把单体优化好:模块化、接口清晰、自动化测试覆盖,一样能扛住业务增长。
但如果你像我一样,被现实逼到墙角——业务复杂、团队协作混乱、某个模块(比如爬虫)老拖后腿——那微服务可能是你的逃生通道。
关键三点:
- 按业务领域拆,不是按技术层拆(别搞什么“DAO服务”、“Controller服务”)
- 资源隔离优先:让不稳定的模块(如爬虫、文件处理)独立部署,别污染核心链路
- 前端要无感:用网关屏蔽后端复杂度,别让前端同事骂你
尾声:在不确定的时代,做确定的事
上周五晚上,我又一次坐在阳台上。这次不是焦虑,而是给新接的单子画架构图。老婆在屋里追剧,房贷照常还,但心里踏实多了。
从被裁的惶恐,到接单的手忙脚乱,再到如今能独立设计并交付一套微服务系统——这一路,没有捷径,只有一个个深夜的调试、一次次客户的质疑、一行行重写的代码。
技术人的价值,从来不是你在哪家大厂,而是你能否在混乱中建立秩序,在限制中创造可能。
微服务也好,单体也罢,不过是工具。真正重要的是:你有没有能力,把一堆零散的需求、有限的资源、焦虑的运营、挑剔的前端,整合成一个能跑起来、能赚钱、能让用户满意的产品。
而我,一个杭州的普通全栈,还在路上。
但至少,我不再害怕下雨夜了。

评论 0