从单体到微服务:我在 Spring Cloud Alibaba 上的生产实战经验
开篇:一段架构演进的故事

2021年,我加入了一个处于快速扩张阶段的电商项目。当时的技术架构是典型的单体应用,部署在 Tomcat 上,数据库用了 MySQL 主从结构,后端开发框架是传统的 Spring MVC,前端 Vue.js。
随着业务增长,系统的复杂度和并发压力陡增。单体架构的问题逐渐暴露:代码臃肿、部署繁琐、功能模块耦合严重、故障影响面大。我们迫切需要一次技术架构的升级。
最终我们选择了 Spring Cloud Alibaba(SCA) 作为微服务化的核心技术栈。这是一次有风险但必须做的尝试。如今回头看这段路,踩过坑、走过弯,但也收获满满。
问题描述:为什么我们需要 Spring Cloud Alibaba?


单体架构遇到的实际问题:
- 发布频繁出错:一个小改动也可能牵一发而动全身。
- 性能瓶颈明显:部分核心接口 QPS 超过临界点,系统开始卡顿甚至崩溃。
- 缺乏服务治理:没有统一的服务发现、限流降级能力。
- 团队协作困难:多个功能模块并行开发时冲突频发,分支管理成本高。
更糟的是,我们在高峰期遭遇了一次大规模雪崩故障,由于某个下游服务调用阻塞导致整个系统瘫痪。
我们需要一个轻量、灵活、国产化程度高且能与阿里云生态无缝集成的微服务解决方案——于是我们把目光投向了 Spring Cloud Alibaba。
解决方案:基于 SCA 的微服务改造之路


我们的目标很明确:将单体拆分为松耦合、独立部署的微服务,并通过合理的架构设计提升系统的稳定性、可维护性与扩展性。
技术选型回顾:
| 组件 | 用途 |
|---|---|
| Nacos | 注册中心 + 配置中心 |
| Sentinel | 服务限流、熔断降级 |
| Dubbo + RestTemplate | 远程调用协议 |
| RocketMQ | 异步消息通信 |
| Seata | 分布式事务 |
| Spring Cloud Gateway | 网关聚合 |
我们并没有一开始就全部引入,而是循序渐进地进行微服务拆分,初期仅使用了 Nacos + Sentinel + Dubbo,后期逐步引入 Seata 和 RocketMQ 等组件。
关键实践:一步步落地微服务架构

第一步:服务注册发现 + 配置管理
我们选择了 Nacos,它不仅是注册中心,还充当配置中心,这对运维非常友好。以前我们用 Spring Cloud Config 做远程配置,但要搭配 Git + Bus Refresh,体验上不如 Nacos 实时推送来的便捷。
示例:Nacos 客户端启动类配置
spring:
cloud:
nacos:
discovery:
server-addr: nacos-host:8848
config:
server-addr: nacos-host:8848
extension-configs:
- data-id: application-${spring.profiles.active}.yaml
group: DEFAULT_GROUP
refresh: true
我们在项目中统一使用 @RefreshScope 来实现动态配置更新,例如:
@Component
@RefreshScope
public class OrderConfig {
@Value("${order.expire-time}")
private int expireTime;
// ...
}
小插曲:最开始上线时,Nacos 集群因为数据同步延迟导致部分服务无法获取配置。我们调整了心跳间隔并做了健康检查的兜底逻辑才解决。
第二步:服务治理:限流、熔断、降级
有了服务发现之后,下一步就是确保服务之间的调用是稳定的。我们采用了 Sentinel,结合 Dubbo 提供了非常好的保护机制。
示例:方法级熔断规则定义
@SentinelResource(value = "queryOrderDetail", fallback = "fallbackQuery")
public OrderDTO queryOrder(String orderId) {
return orderService.getOrder(orderId);
}
// 降级方法
public OrderDTO fallbackQuery(String orderId, Throwable ex) {
log.warn("触发订单服务降级");
return new OrderDTO().setFallback(true);
}
Sentinel Dashboard 是个好工具,可以实时看到 QPS、异常数、响应时间等指标。我们在压测阶段利用它做热点参数限流,防止恶意刷单行为带来的冲击。
第三步:服务间通信的选择
我们最初尝试过 Feign + LoadBalancer,但在高并发场景下出现了连接池打满的情况,后来转向了 Dubbo + Netty 构建的服务调用体系,性能更加稳定。
Dubbo 在异步编程模型、线程池管理方面比传统 HTTP 更加灵活,也更适合 Java 微服务之间高性能通信的需求。
Dubbo 接口定义:
@DubboReference(retries = 2)
private UserService userService;
我们同时保留了基于 RESTful 的对外 API,采用 Spring Cloud Gateway 进行统一聚合路由。
第四步:异步解耦与分布式事务
为了处理库存扣减、积分变动、通知推送等跨服务协同的操作,我们引入了 RocketMQ。
对于一些强一致性要求的场景,比如支付成功后扣库存、更新订单状态等,我们使用了 Seata 来实现 TCC 模式下的分布式事务。
示例:TCC 分段提交
@TwoPhaseBusinessAction(name = "deductStock")
public boolean deductStock(BusinessActionContext ctx);
@Commit
public boolean commit(BusinessActionContext ctx);
@Rollback
public boolean rollback(BusinessActionContext ctx);
刚开始用 Seata 时,经常出现全局事务未提交导致数据锁住。经过排查发现是某些服务节点宕机未能正确上报状态。后来我们对事务协调器做了 HA 改造,并增加了超时自动回滚机制,效果显著。
踩坑经验分享:那些深夜调试的小故事
1. Dubbo 泛化调用 vs 参数类型丢失
某次灰度发布后,线上订单服务偶尔会抛出 “NoSuchMethod” 的错误。排查发现是因为某个服务消费者使用的泛化调用(GenericService),而提供方新增了重载方法但未做好兼容处理。
解决办法:给所有泛化调用添加唯一标识符(如 methodKey),并确保版本号变更时兼容处理。
2. Sentinel 控制台与本地配置优先级混乱
有一次上线后,限流规则失效,原因是本地配置文件里设置了相同的资源名,覆盖了 Sentinel 控制台下发的规则。
建议做法:控制台应设为最高优先级;如果希望保留部分静态规则,需明确命名空间与隔离策略。
3. Nacos 集群脑裂问题导致服务不可用
初期我们只用两个 Nacos 节点做集群,后来在压测期间发现有“脑裂”现象,即一部分节点失联后仍然认为自己处于“Leader”,从而造成数据不一致。
解决方案:改用三个节点部署,启用 Raft 协议,并关闭短连接模式。
效果总结:架构升级带来的实际收益
性能层面:
- 平均响应时间从 150ms 降至 60ms;
- 支持更高并发请求,QPS 提升约 30%;
- 同时支持多环境部署,测试/预发/生产互不影响。
运维层面:
- 发布效率提升明显,服务可独立部署,滚动升级平滑;
- 系统容错能力增强,即使部分模块故障也不会导致整体瘫痪;
- 监控体系完整,通过 Prometheus + Grafana 实现服务健康可视化。
团队协作层面:
- 模块清晰划分,团队分工更明确;
- 新人接入成本降低,文档+SDK 使用指南足够支撑日常开发。
我的经验与建议:给正在微服务化的你
1. 不要一开始就把所有组件都搭起来
我见过太多项目上来就搞 Nacos + Sentinel + Seata + RocketMQ + Zipkin,结果连基础服务调用都没跑通。先聚焦核心链路,解决最痛的问题。
2. 微服务不是银弹,不要过度拆分
业务边界模糊、数据强关联的服务强行拆分会带来更高的维护成本。要权衡拆分粒度和协作成本之间的关系。
3. 日志监控体系建设要前置
我建议尽早引入 ELK + SkyWalking,尤其是日志分析和全链路追踪。它们在排查线上问题时作用巨大。
4. 注意接口设计的契约性与向前兼容
接口版本控制很重要,尤其在多人协作时。我们早期犯过接口返回字段直接删除的错误,导致下游系统大面积报错。后来统一使用 Protocol Buffer 或 JSON Schema 定义接口规范。
结语:技术是手段,不是目的
Spring Cloud Alibaba 是一套非常好用的微服务框架,尤其适合国内团队。它融合了很多阿里内部的最佳实践经验,具备很强的可用性和灵活性。
但我始终相信,再好的技术也是服务于业务需求的。在我参与的这个项目中,真正的挑战从来都不是“会不会用 Dubbo”、“能不能对接 RocketMQ”,而是在不断变化的需求中找到“架构的平衡点”。
如果你也在做类似的转型或者准备踏入微服务的世界,希望这篇文章能带给你一些启发和底气。愿你在编码的路上越走越远,代码越写越稳!
📌 如果你也有关于微服务的实战问题,欢迎留言交流,我可以结合自己的经验一起探讨。

评论 0