从单体到分布式:我在南山写微服务的这一年
我叫阿凯,坐标深圳南山,一个从测试转开发的3年经验选手。2025年初,我跳到现在这家做SaaS的创业公司,月薪从15k涨到22k。入职第三周,CTO把我叫进会议室:“公司准备把核心系统从单体拆成微服务,你负责订单模块。”当时我脑子里就一个念头:我连.NET的中间件管道都没搞明白,你让我拆微服务?
那个让人头秃的单体
我们做企业级工单管理系统,技术栈是.NET 8。原来的系统是一个典型的“大泥球”单体,订单、库存、用户、通知模块互相调用,靠直接引用项目。每次发布全量部署,CI/CD流水线跑一次要40分钟。最离谱的是有一次,库存模块改了个字段类型,订单模块直接编译报错,通知模块运行时抛异常。
果然,去年双十一前夕,系统挂了。通知模块里一个死循环把内存吃满,整个单体直接OOM,所有模块一起陪葬。CTO凌晨两点发消息:“明天开始,启动微服务拆分。”我因为平时写测试脚本对业务逻辑最熟,被点名负责订单服务。
拆服务不是切蛋糕
真正动手才知道,微服务拆分远不是把文件夹拆开那么简单。数据库怎么办?事务怎么办?服务发现怎么做?
选型过程本身就很折腾。CTO拍板:“我们.NET团队,换语言等于自废武功。”于是定了.NET 8 + gRPC + RabbitMQ + Consul这套组合。.NET在微服务这块的文档比Java少得多,很多问题只能靠啃源码和翻GitHub Issues。
拆数据库是最痛苦的一步。原来所有表全在一个库里,外键约束写得飞起。拆成独立服务后,跨服务的数据一致性怎么保证?我一开始想用分布式事务,结果被老张一顿教育:“你上分布式事务,还不如不拆。性能直接打回解放前。”
最后我们用了最终一致性方案:订单服务创建订单后,发消息到RabbitMQ,库存服务消费消息扣减库存,失败就发补偿消息回滚订单状态。听起来优雅,但写起来全是坑。消息重复消费怎么办?消息丢失怎么办?我花了一个周末写了一套幂等表,每个消息带一个全局唯一的MessageId,消费前先查表,消费完插入记录。周一演示时老张点点头:“有点意思,但你这个表会不会变成新的瓶颈?”
我愣住了。确实,所有服务都依赖这张幂等表,它自己不就成了新的单点?后来我们改成了Redis缓存+数据库兜底,Redis挂了就降级查库,性能才勉强达标。
意外闯进AI辅助开发的世界
拆到第三个月,订单服务里的业务规则越来越多,满减、折扣、优惠券叠加逻辑像意大利面条一样缠在一起。每次产品加一个新规则,我就要改一堆if-else,然后重新部署。测试用例从200个涨到800个,我写得手都麻了。
有次刷视频了解到 Dify 这个开源平台,可以可视化搭建AI工作流。我突然想到:能不能用AI辅助处理那些复杂的订单规则?
第二天我在开发群里提了这个想法,结果被群嘲:“阿凯,你写微服务写魔怔了吧,AI能写业务代码?”只有老张没笑,他私聊我:“你试试呗,反正也不亏。”
Dify的上手体验对.NET开发者挺友好,Docker Compose一键部署,不需要懂Python。我在本地起了个Dify实例,把订单服务的接口文档喂给大模型,建了一个简单的Agent:输入自然语言问题,输出对应的API调用建议。效果意外地好,虽然不是100%准确,但至少能帮我理清思路,省掉大量翻文档的时间。
真正让我兴奋的是,Dify支持**多智能体(Multi-Agent)**模式。我建了两个Agent:一个负责解析业务规则,一个负责生成测试用例。两个Agent互相协作,一个输出规则文档,另一个根据文档生成对应的xUnit测试代码。我只需要做最后的审查和微调。那段时间我的测试用例产出速度直接翻倍,加班时间明显少了。
Kiro 带来的转折
今年年初,微软发布了.NET的AI开发工具 Kiro。老张在群里发消息:“Kiro支持直接集成到Visual Studio,可以帮你生成微服务代码,你们试试。”
我抱着试试看的心态装了Kiro插件。第一次用是写订单服务的gRPC接口。我在注释里写了一句:“实现一个根据用户ID查询最近30天订单列表的方法,需要分页和排序。”然后按下了快捷键。
Kiro生成的代码让我有点惊讶。它不仅仅是生成了一个方法框架,还自动处理了分页参数校验、排序字段白名单、以及和仓储层的交互。甚至还在返回值里加了next_page_token,这是我在原型设计文档里提过但还没实现的字段。
当然,Kiro也不是万能的。它生成的代码有时候会引入一些奇怪的设计,比如有一次它自作主张地加了一个OrderQueryBuilder类,用了建造者模式,但我们的项目里根本没有这种风格。最后我删掉重写了一半。不过总体来看,Kiro让我在写样板代码上省了不少时间,可以把精力放在真正的业务逻辑上。
有了Kiro和Dify的组合,我逐渐摸索出了一套自己的开发流:用Dify的多智能体做需求分析和测试用例生成,用Kiro做代码骨架生成,自己专注于核心业务逻辑和架构决策。
那些踩过的坑
第一个坑:服务拆分粒度太细。 我们一开始把订单服务拆成了订单查询服务和订单写入服务,理由是读写分离。结果两个服务共享同一个数据库,部署要同步,出问题要一起排查,完全没有享受到独立部署的好处。后来我们合并回一个订单服务,内部用CQRS模式做读写分离,舒服多了。微服务拆分不是越细越好,边界清晰才是关键。
第二个坑:过度依赖框架。 我们用了Consul做服务发现,一开始每个服务都直接通过Consul HTTP API拿实例列表。后来发现网络抖动时服务发现会超时,导致调用链全断。最后我们引入了客户端缓存和重试机制,才算稳住。框架只是工具,容错和降级得自己设计。
第三个坑:测试环境成本爆炸。 服务拆多了之后,本地开发环境要起七八个容器,我的16G内存MacBook直接冒烟。后来我们用Docker Compose按需启动,只跑自己改的服务,依赖的服务用Mock Server代替。虽然Mock有时候和真实行为有偏差,但至少开发体验好了很多。
写在最后
从测试转开发这条路,我走得不算轻松。去年刚接手微服务拆分的时候,我几乎每周都有那么一两天想辞职回老家考公。但坚持下来之后回头看,那些熬夜看文档、被生产环境教做人的日子,确实让我成长了不少。
上个月,CTO在全员会上说:“订单服务的稳定性比单体时期提升了80%,阿凯功不可没。”那一刻,我觉得所有的头发都没有白掉。
如果你也在考虑从单体拆到微服务,我的建议是:别急着动手,先想清楚你的业务到底需不需要微服务。如果团队只有三五个人,单体+模块化可能更适合你。如果确实要拆,那就做好长期作战的准备,把监控、日志、链路追踪这些基础设施先搭好,再谈拆分。
至于AI工具,Dify和Kiro确实帮了我大忙,但它们只是辅助。真正决定架构成败的,还是你对业务的理解和对技术细节的把控。工具可以帮你写代码,但帮不了你做决策。

评论 0