请写一篇关于【微服务架构设计实战:从单体到分布式】的技术文章
去年十月的一个周五晚上,杭州下着小雨。我窝在城西那套68平的小两居里,盯着电脑屏幕上的IDEA,手指在键盘上敲得飞快,却怎么也调不通那个该死的Feign超时配置。
老婆在厨房煮面,香味飘进来,我却一点胃口都没有。房贷每月要还6300块,信用卡账单刚还完,而公司最近又在搞“降本增效”——说白了就是裁员预警。我一边改bug,一边刷BOSS直聘,心里七上八下。
就在这时,钉钉弹出一条消息:“下周开始,把订单模块拆出来,做成独立服务。”
我愣了一下,手里的咖啡差点洒在键盘上。微服务?我们这坨运行了五年的单体应用?
一、单体之痛:一个老程序员的深夜崩溃
我在这家电商SaaS公司干了四年,从Java初级一路干到后端组长。系统最初是用Spring Boot写的单体架构,前端Vue,数据库MySQL + Redis缓存。一开始跑得挺欢,日活几千用户的时候稳如老狗。
但随着客户越来越多,系统越来越臃肿。最夸张的时候,一个Git提交动辄影响十几个业务模块。有一次我改了个优惠券逻辑,结果把支付回调给干挂了,半夜三点被电话叫起来救火。
更别提部署了——每次上线都像打仗,全站停服15分钟,运维同事边敲命令边骂娘。测试环境和生产环境还不一致,经常出现“在我机器上是好的”这种经典桥段。
技术债堆成山,人却越招越少。
去年九月,公司裁掉一半实习生,连两个三年经验的Python后端都被优化了。老板开会说:“我们要聚焦核心,提升效率。”翻译成人话就是:人少了,活不能少,你们自己想办法。
那段时间我焦虑得睡不着觉。每天晚上躺在床上想:要是失业了怎么办?房子贷款怎么办?要不要转行送外卖?(开玩笑的,但真搜过美团骑手的招聘要求)
二、转机:一场意外的求职面试
事情的转折发生在一个意想不到的地方——求职。
十月初,我实在扛不住压力,偷偷更新了简历,投了几家大厂。没想到居然收到了一家做智能硬件的公司的面试邀请,岗位是“高级Java工程师(微服务方向)”。
面试官是个戴眼镜的中年大哥,聊得很实在。他没问什么八股文,反而直接甩给我一个场景题:
“假设你有一个单体电商系统,现在要拆成微服务。你会怎么拆?怎么保证数据一致性?如何监控链路?”
我硬着头皮讲了点理论:按业务域拆分、用Nacos做注册中心、Sentinel限流、Seata处理分布式事务……但说到具体落地细节,就有点虚了。
面试结束前,他笑了笑说:“兄弟,你基础不错,但实战经验还是少了点。微服务不是换个框架就行,它是一整套工程体系。”
那句话像根针,扎醒了我。
回家路上,我坐在地铁上想:与其等公司被动改造,不如我自己先动手练起来!
三、实战:从“Hello World”到真正的微服务
说干就干。我用周末时间,在家里搭了一套最小可行的微服务架构。
第一步:拆分业务边界
我拿公司项目脱敏后的简化版当练手素材。原来的单体应用包含:用户、商品、订单、支付、库存五大模块。
按照DDD(领域驱动设计)的思想,我画了张草图:
- user-service:负责用户注册、登录、个人信息
- product-service:商品管理、分类、搜索 Assistant:
- order-service:创建订单、查询订单状态
- payment-service:对接第三方支付(模拟)
- inventory-service:库存扣减、回滚
每个服务独立数据库,用Spring Boot + MyBatis-Plus开发,接口用OpenAPI 3.0规范定义。
第二步:服务通信与注册发现
我选了Nacos作为注册中心+配置中心。本地启动五个服务,自动注册上去,互相通过服务名调用。
跨服务调用用的是Feign + Ribbon(后来升级成Spring Cloud LoadBalancer)。第一次调通时,我兴奋地喊老婆来看:“你看!user-service 能直接调 product-service 了!”
她一脸茫然:“所以……今晚能加个鸡腿吗?”
第三步:分布式事务的坑
最大的挑战来了:下单时要扣库存+创建订单+记录支付流水,这三个操作必须原子性。
我先是尝试用TCC模式(Try-Confirm-Cancel),写了一堆补偿逻辑,结果代码复杂到自己都看不懂。有一次网络抖动,Cancel没执行,库存多扣了,差点哭出来。
后来改用Seata的AT模式,配合全局事务ID(XID),虽然性能有损耗,但开发简单多了。关键是在数据库加了undo_log表,Seata会自动生成反向SQL。
💡 小技巧:本地调试时,我故意在payment-service里抛异常,看order和inventory能不能回滚。成功那一刻,感觉比当年拿到offer还爽。
第四步:链路追踪与监控
没有可观测性的微服务就是裸奔。我集成了SkyWalking,所有服务加一行agent参数,就能看到完整的调用链。
比如一次下单请求:
[Gateway] → [Order-Service] → [Inventory-Service]
↘ [Payment-Service]
每个环节的耗时、错误率一目了然。上周五晚上,我发现inventory-service响应突然变慢,点进去一看,是数据库连接池满了——原来是忘了调大HikariCP的maxPoolSize。
这种问题在单体里根本发现不了,因为所有SQL混在一起。
四、语言之争:Java vs Python,我的真实选择
很多人问我:微服务非得用Java吗?能不能用Python?
说实话,看场景。
我司历史项目是Java栈,团队熟悉Spring生态,用Java顺理成章。而且Java在高并发、稳定性、JVM调优方面确实有优势,尤其对接阿里系中间件(比如RocketMQ、Sentinel)无缝集成。
但我也用Python写过辅助服务,比如:
- 一个定时任务服务,用Celery + Redis处理夜间报表生成
- 一个数据清洗服务,用Pandas处理CSV导入
结论:核心交易链路用Java,边缘工具类服务可以用Python。不要为了技术而技术。
顺便吐槽一句:有些面试官非要问“Java和Python哪个好”,我觉得这问题就像问“老婆和妈掉水里先救谁”——看你站在哪条船上。
五、算法?别慌,它没你想的那么玄
说到算法,很多考公/转行的朋友一听就头大。其实微服务里用到的算法,远没有LeetCode Hard那么变态。
举几个真实例子:
- 服务路由时用一致性哈希分配流量
- 限流用令牌桶算法(Sentinel底层)
- 分布式ID生成用雪花算法(Snowflake)
- 缓存淘汰策略用LRU
这些我都自己手写过demo。比如雪花ID,核心就几十行代码:
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) throw new RuntimeException("Clock moved backwards");
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) timestamp = tilNextMillis(lastTimestamp);
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
重点不是背代码,而是理解思想。 面试时能讲清楚“为什么用这个算法”、“有什么trade-off”,比默写快排强一百倍。
六、从技术到人生:微服务教会我的事
折腾这套微服务架构花了我三个月业余时间。期间熬过夜、吵过架(老婆嫌我总对着电脑)、甚至想过放弃。
但坚持下来后,变化悄然发生:
- 技术自信回来了。我不再怕“分布式”“高并发”这些词,因为亲手做过。
- 求职有了底气。今年三月,我拿到一个22k的offer(比现在15k涨了近50%),虽然最后没去——因为我决定考公。
- 思维方式变了。微服务讲究“高内聚低耦合”,做人也一样:专注自己的核心职责,别瞎操心别人的事。
是的,你没看错。我现在白天上班写代码,晚上刷行测申论。目标是浙江省考的信息化岗位。
为什么考公?
很简单:稳定。经历过互联网寒冬,看过同事抱着纸箱离开写字楼,我才明白——技术再牛,也扛不住行业周期。而公务员,至少能让我安心还完那6300的房贷。
老婆支持我:“你考上了,我就不用天天担心你被裁了。” 她甚至帮我整理错题本,虽然她连什么是“熔断机制”都不知道。
七、给同行的几点建议
如果你也在单体架构里挣扎,或者想转型微服务,分享几点真心话:
- 别追求一步到位。先拆一个非核心模块试水,比如通知服务、日志服务。
- 基础设施比代码重要。CI/CD、监控告警、日志聚合,这些才是微服务的命脉。
- 文档和规范必须跟上。我们团队现在强制要求:每个服务必须有README,说明依赖、接口、部署方式。
- 别忽视软技能。微服务意味着更多跨团队协作,沟通成本飙升。学会写清晰的PR描述,比炫技更重要。
最后,技术是手段,不是目的。无论是写代码、考公,还是送外卖(再次声明我没送),目标都是让生活更好一点。
结语:在不确定的时代,做确定的事
写这篇文章时,窗外杭州的梅雨季刚结束,阳光难得露脸。我泡了杯龙井,看着阳台上那盆老婆养的薄荷长得郁郁葱葱。
回想这一年,从焦虑失眠到重拾信心,从单体泥潭到微服务实践,从犹豫要不要跳槽到坚定考公——每一步都不容易,但每一步都算数。
技术会过时,框架会淘汰,但解决问题的能力永远值钱。
无论你是在大厂卷P8,还是在小公司维护祖传代码,或是像我一样准备上岸,记住:
真正的架构,不在代码里,而在你面对混乱时的那份清醒与坚持。
共勉。
—— 一个正在刷《行测5000题》的Java程序员
2024年6月于杭州

评论 0