为什么要拆?
我们的核心业务跑在单个 Spring Boot 仓库里,五年积累下来,编译一次要三分钟,改一个字段要动五个模块,部署窗口卡在凌晨两点——团队规模从 3 人涨到 12 人后,协作摩擦大到没法忽视。
不是我拍板要拆的。是某天测试环境再次因为一个无关模块的重启挂掉之后,测试组长在群里发了一句"能不能把 X 模块单独拎出来"。这句话成了导火索。
拆之前没想清楚的事
1. 数据库是最大的债
单体时,所有模块共用一个数据库,外键约束、跨模块 join 是家常便饭。拆服务时,你不可能一夜之间把所有表按服务边界分库——迁移周期可能长达半年。这半年里,多个服务共用同一个库,"微服务"其实只是"分布式单体"。
拆服务的第一步不是写新代码,而是理清数据归属。
2. 团队认知对齐比技术方案更难
架构方案写得很漂亮,但团队成员对"为什么要拆""拆完之后各自负责什么"的理解参差不齐。有人觉得微服务就是"每个模块独立部署",有人理解为"每个服务独立数据库"。认知不对齐会导致实施阶段反复返工。
我的建议:在拆之前,组织一次全员技术会议,把拆分边界、数据归属、团队分工画成一张大图贴到墙上。每天站会都对着这张图说话。
实际怎么拆的
我们用了绞杀者模式(Strangler Fig Pattern):先在网关层做路由分流,新功能直接写到新服务里,旧功能逐步迁移。迁移一个下线一个,保持系统始终可运行。
// 网关路由配置示例
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service关键原则:旧接口不改行为,只改路由。让网关做透明代理,对前端无感。
踩过的坑
分布式事务是最痛的。单体时一个 @Transactional 搞定的事,拆完之后跨服务调用要用 Seata 或者最终一致性方案。我们的选择是:核心链路用 Seata AT 模式,非核心链路用消息队列 + 本地事务表做最终一致。
不是所有跨服务操作都需要强一致。想清楚业务能不能容忍短暂不一致,再选方案。
值不值?
拆完三个月回头看:编译时间从三分钟降到四十秒,部署可以按服务独立发布,团队各自迭代互不阻塞。但代价是运维复杂度翻倍——监控、日志、链路追踪全都要上。
如果你团队不到 5 人、业务变化不频繁,单体仍然是最好的架构。微服务不是银弹,是组织规模倒逼出来的工程妥协。
评论 (5)