从“踩坑”到“落地”:我在生产环境使用 Spring Cloud Alibaba 的真实经历

孙军♪
2025-06-24 02:35
阅读 700

开篇:一次架构升级的契机

开篇:一次架构升级的契机

我是公司后端研发团队的一员,主要负责平台核心业务模块的开发与维护。我们是一个中型互联网公司,早期采用的是传统的单体架构,随着业务发展和用户量增长,服务开始频繁出现性能瓶颈,代码臃肿、部署困难、版本更新风险高等问题逐渐暴露出来。

为了应对这些挑战,公司决定进行微服务架构改造,而 Spring Cloud Alibaba(以下简称 SCA)成为我们的首选技术栈。一方面它基于 Spring Cloud,学习成本低;另一方面对阿里云生态支持好,对于我们正在逐步上云的技术路线非常契合。

今天就来分享一下我在这个过程中的一些实践经验,包括项目背景、遇到的问题、技术选型背后的考虑、关键实现点以及那些让人头大的“坑”。


项目背景:一个典型的电商后台系统

项目背景:一个典型的电商后台系统

改造的目标是公司的订单中心和库存管理系统。这两个系统虽然拆分得不彻底,但已经存在多个子功能模块,比如:

  • 订单状态同步
  • 库存扣减
  • 售后订单处理
  • 异常订单监控

在之前的单体架构下,所有逻辑都在同一个工程里,通过本地事务管理数据一致性,日志和服务间调用都是内聚的。但在高并发场景下,经常出现线程阻塞、服务超时、接口响应慢等问题。

于是我们决定将整个系统拆分成以下几个微服务:

服务名称 职责说明
order-service 负责订单创建、状态变更等
inventory-service 处理库存相关业务
logistics-service 物流信息推送与查询
gateway-service 网关,统一对外提供 API 接口
config-server 统一配置中心

接下来就是选择合适的技术栈,Spring Boot + Spring Cloud 当然是主角,但在国内环境下,Spring Cloud Alibaba 可以说是如鱼得水,尤其在服务发现、限流、降级等方面提供了更成熟的解决方案。


遇到的第一个大问题:服务注册发现怎么搞?

遇到的第一个大问题:服务注册发现怎么搞?

问题描述

最初我们在服务注册这一块选择了 Eureka,但很快发现两个问题:

  1. 服务节点上下线感知慢:Eureka 默认的注册时间偏长,节点宕机后仍会保留一段时间的服务实例;
  2. 中文文档少、社区活跃度低:我们团队对英文文档不太友好,出问题很难快速定位。

于是我们转向了 Nacos,这是 Spring Cloud Alibaba 提供的服务注册与配置中心组件,支持动态服务发现、健康检查、分布式配置管理,非常适合国内项目。

解决方案

引入 spring-cloud-starter-alibaba-nacos-discovery 后,只需要添加如下依赖和配置:

<!-- pom.xml -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
# application.yml
server:
  port: 8080
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # nacos 地址

然后启动类加上注解即可完成服务注册:

@EnableDiscoveryClient
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

服务之间调用我们使用 OpenFeign + LoadBalancer,Nacos 自动集成了 Ribbon,服务调用变得简单又高效。


第二个痛点:服务雪崩怎么办?熔断限流刻不容缓

第二个痛点:服务雪崩怎么办?熔断限流刻不容缓

问题描述

当我们将各个服务上线后,第一次压测就遇到了严重问题——库存服务被大量并发请求击穿,导致整个系统崩溃。这个问题让我们意识到,必须对服务链路进行保护。

技术选型:Sentinel 上场

我们果断引入了 Sentinel,它提供了丰富的限流、熔断、系统自适应保护等功能,并且与 Spring Cloud 集成非常方便。

关键配置与使用方式:

添加依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

开启 Sentinel Web 过滤器保护入口 API:

# application.yml
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080 # sentinel 控制台地址
      eager: true

然后你可以直接使用 @SentinelResource 注解来定义资源并绑定异常处理器:

@GetMapping("/deduct")
@SentinelResource(value = "deductInventory", fallback = "handleError")
public Result deductInventory(@RequestParam String productId, @RequestParam Integer count) {
    // 实际业务逻辑
}

public Result handleError(Throwable t) {
    return Result.fail("当前库存服务繁忙,请稍后再试");
}

此外,Sentinel Dashboard 还可以实时观察每个资源的 QPS、线程数、异常率等指标,并设置动态规则,极大地增强了系统的可观测性和可控性。


数据库设计的小细节:分库分表初体验

虽然不是 Spring Cloud Alibaba 的范畴,但微服务化后数据库也面临压力剧增的问题。我们原来的库存和订单表都集中在一张主表中,读写混合严重,性能下降明显。

因此我们做了如下调整:

分库策略

按用户 ID Hash 划分,将订单分布到不同库中:

用户ID % 4 所属库名
0 order_db_0
1 order_db_1
2 order_db_2
3 order_db_3

这样既保证负载均衡,又能避免热点数据。

表结构拆分

原订单表:

CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    status VARCHAR(20),
    create_time DATETIME,
    update_time DATETIME
);

现在根据业务属性拆分为两张表:

  • orders_base: 存储订单的核心字段(如订单编号、用户ID、商品ID)
  • order_status: 存储状态变更记录,单独建索引便于查询

这样不仅提升了写入性能,也减少了锁竞争。


生产部署那些事儿:运维上的小技巧

微服务跑起来以后,真正的挑战才刚刚开始:如何保障稳定性?如何排查故障?

1. 日志聚合

我们在每一台服务器部署了 Filebeat,将日志采集后发送至 ELK(Elasticsearch + Logstash + Kibana),通过 Nacos 公共配置,统一指定日志输出路径和格式,极大地方便了线上问题的追溯。

2. Prometheus + Grafana 监控体系

我们为每个微服务集成 micrometer-registry-prometheus,并通过 Prometheus 定期拉取指标,使用 Grafana 展示 QPS、响应延迟、线程池状态等关键指标。

示例代码片段:

management:
  metrics:
    tags:
      application: ${spring.application.name}
  endpoints:
    enabled-by-default: true
    web:
      exposure:
        include: "*"

Prometheus 配置文件中加入:

scrape_configs:
  - job_name: 'sca-services'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets:
        - 'order-service:8080'
        - 'inventory-service:8080'

有了这个体系后,我们可以在 Grafana 中一眼看出哪些接口最耗时、哪里出现异常抖动。

3. 滚动发布+灰度上线

为了避免一次性全量上线带来的不稳定因素,我们采用了滚动发布策略,配合 Kubernetes 的滚动更新机制,让新老版本并行运行,直到确认没问题再全部切换。

另外我们还使用了 Nacos 动态路由能力,在网关层实现了灰度流量控制,比如可以针对某些测试账号定向打向新版本服务。


踩过的坑 & 对策总结

负载均衡配置-1

坑点1:Nacos 服务注册失败频繁?

一开始我们把所有的服务都部署在同一台机器上,没有合理分配内存。结果 Nacos 经常因为 OOM 被重启,导致服务频繁失联。

对策:给 Nacos 单独部署独立机器或容器,调整 JVM 内存参数(比如 -Xms2g -Xmx2g

坑点2:Feign 调用超时默认值太短?

默认的 Feign 超时是 1 秒,这在某些复杂业务场景下根本不够,尤其是首次启动服务还没完成预热的时候。

对策:手动修改 Feign 和 Ribbon 超时配置:

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000

坑点3:Sentinel Dashboard 规则重启丢失?

刚用 Sentinel 时我们发现每次重启 Dashboard,之前配置的限流规则都会失效。

对策:结合 Nacos 配置中心持久化 Sentinel 规则。在 Dashboard 中启用 --nacos-namespace-id 参数,将规则推送到 Nacos 存储。


效果与收益总结

经过近半年的打磨,目前这套基于 Spring Cloud Alibaba 构建的微服务体系已经在生产稳定运行了超过三个月,日均处理订单量提升 3 倍,API 平均响应时间由原来的 400ms 缩短到 150ms。

具体收益包括:

  • 稳定性增强:熔断限流机制有效防止了服务雪崩
  • 弹性扩容:服务可以根据负载水平自动伸缩,节省了不少服务器资源
  • 研发效率提升:标准化的微服务模板和公共组件复用,新人上手更快
  • 可观测性加强:完善的监控告警和日志体系让排查问题不再盲目

一点感悟 & 给读者的建议

说实话,刚开始接触 Spring Cloud Alibaba 的时候,我也曾迷茫过,特别是面对这么多组件(Nacos、Sentinel、Seata、RocketMQ...),不知道该学哪个、用哪个。

但后来我发现,技术是服务于业务的工具,不是炫技的对象。在项目初期,不需要把所有组件都上马,而是应该围绕核心业务问题,选择最关键的几个解决点来入手。

如果你正准备使用 Spring Cloud Alibaba,这里是我的几点建议:

  1. 从 Nacos 开始,不要一开始就上 RocketMQ 或 Seata
    微服务的基础是注册发现、配置管理,把这些先搞懂,后面的组件才能发挥更大作用。

  2. 重视服务治理能力,尽早接入 Sentinel 或 Hystrix
    不然你迟早会遇到“调用链爆炸”的问题。

  3. 提前做好服务监控方案
    Prometheus + Grafana 是非常成熟的选择,值得投入时间搭建。

  4. 别怕改架构,但要有节奏地推进
    我们也是边跑边修,逐步迭代,不是一口气重写的。

最后想说一句:微服务从来都不是银弹,它能带来灵活性,也会引入更多复杂度。只有深入理解你的业务场景,找到平衡点,才是技术落地的关键。

如果你也在做微服务转型,或者在用 Spring Cloud Alibaba,欢迎留言交流,一起成长 👇


本文首发于个人博客,作者:阿乐,一个喜欢写代码也喜欢写文章的程序员。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝