微服务拆分到底拆到多细?我踩了3年坑的经验总结

📅 2026/7/22 2:34:29 👁️ 阅读次数 📝 编程学习
微服务拆分到底拆到多细?我踩了3年坑的经验总结

做了这么多年开发,我踩过最深的坑就是"为了微服务而微服务"。

2020年我第一次带团队做微服务拆分,当时觉得"不拆就不是现代架构",结果拆完以后,10个人的团队维护20个服务,每次改需求要跨3-5个服务发版,上线时间从原来的半天变成三天。那段时间我最大的感悟是:微服务是要付出代价的。

后来陆续做了几次拆分和合并,慢慢总结出一套经验。今天聊聊我自己的判断方法和实操过程,不是教科书那套,是真正踩过坑之后沉淀下来的东西。

一、什么时候该拆?

很多文章会告诉你"代码量到多少行就该拆了",但我觉得真正的判断标准不是行数,而是协作成本。

我一般看这几个信号:

部署频率明显下降。一个功能改完了,因为和其他模块耦合在一起,别人改的东西还没测完,你的代码就上不了线。如果两周才能发一次版,说明单体已经开始拖慢你了。

代码冲突变多。每次合并都有人在同一个文件上打架,尤其是那种"我也不想改但没办法"的冲突,说明模块边界已经模糊了。

故障面太大。用户模块的一个小bug,导致整个服务不可用,所有模块一起遭殃。这个最疼,也最容易被忽视——因为大家习惯了"重启大法"。

你可以看看自己的项目,如果中了3条以上,是可以认真考虑拆分了。但说实话,如果团队只有三四个人,拆了反而是负担,运维成本会把你们压垮。小团队老老实实用单体,模块化做好,比什么都强。

二、怎么拆?

我见过最蠢的拆分方式是按技术层拆——“把Controller单独拆出来”、“把Model独立成服务”,这是纯属给自己加戏。

正确的拆法是按业务能力。举个例子,一个电商系统,你应该先画清楚业务域:

用户域管注册登录权限,商品域管库存和分类,订单域管下单支付退款。每个域之间通过事件通信,不直接调数据库。

判断标准很简单:一个域的数据改了,其他域需不需要同步知道?不需要,那就是独立服务的候选。

实际拆的时候,别想着一步到位。我用的方法是"绞杀者模式",说白了就是先挑一个最容易独立的模块,给它单独建个API层,然后把调用方一个个迁过去,最后把老代码删掉。一次只拆一个,拆完一个验证一个,验证通过再拆下一个。

从哪个模块开始拆?我建议按两个维度排序:变化频率和资源消耗。变化多又吃资源的,比如搜索推荐,优先拆。变化多但消耗小的,比如用户权限,次优先。变化少消耗大的,比如日志报表,看情况。两头都低的,最后再说。

三、拆完以后什么最坑?

我踩过最大的坑是分布式事务。

单体里一个数据库事务解决的问题,拆成微服务后变成了分布式事务。你查一下Saga模式,但说实话,最好的办法不是用什么模式,而是重新设计业务边界,让事务落在一个服务内部。如果实在避免不了,那优先用最终一致性,别强求强一致。

第二个坑是调用链太长。A调B,B调C,C调D。链越长,任何一个环节出问题都会被放大。我的经验是调用链深度控制在3层以内,超过3层的用异步消息替代。

第三个坑也是最常见的——服务拆了,数据库没拆。所有服务还在读写同一个库,你拆了个寂寞。每个服务必须有自己的数据库或者自己的schema,服务间数据交换只走API,不走数据库。

四、总结一下我的经验

拆到什么程度算合适?我给自己定了一个标准:一次需求变更需要修改的服务数不超过2个。如果超过了,说明拆太细了,合并回去。

微服务架构的成熟度不是看你拆了多少个服务,而是看你能不能独立部署、独立测试、独立扩容任何一个服务,而对业务没有重大影响。

最后说一句,如果现在让我重来,我会先花一两个月把单体内部的模块边界理清楚,再考虑拆的事。模块化做好的单体,比拆得稀碎的微服务好用十倍。

这篇文章写到这,我自己的博客(aigcharness.com)上还有一些具体的架构选型和工程实践文章,有兴趣可以看看,都是真实项目里沉淀下来的东西。