从 Spring Boot 到 Spring Cloud:一个后端开发者的微服务实战之路

延迟优化师
2025-06-28 09:28
阅读 774

背景介绍:为什么要用 Spring Cloud?

背景介绍:为什么要用 Spring Cloud?

几年前,我所在的公司还是一家使用单体架构的中小型电商平台。随着业务快速发展,系统开始变得臃肿,部署效率低、维护成本高、团队协作难等问题逐渐显现出来。当时我们尝试过模块化拆分,但收效甚微。

后来,在一次技术分享会上,我第一次接触到“微服务”这个词,特别是看到 Spring Cloud 在分布式系统中提供的服务治理能力时,内心有种“终于找到解药”的感觉。于是我们决定,把老项目迁移到微服务架构上来,而 Spring Cloud 成为了我们的首选工具链。

这篇文章将结合我当时参与的一个完整转型项目,带大家一步步了解如何从零开始搭建一个基于 Spring Cloud 的微服务架构体系。


我们遇到了哪些问题?

我们遇到了哪些问题?

当时系统的主要痛点有:

  1. 代码库庞大:前后端混合在一个工程里,核心功能如订单、用户、商品都耦合严重,修改一处可能引发全站故障。
  2. 部署困难:每次上线都要全量发布,动辄十几分钟,影响用户体验。
  3. 扩展性差:高峰期服务器扛不住流量压力,无法快速横向扩展。
  4. 开发协同难:不同小组修改同一个项目容易冲突,版本控制复杂。

这些问题最终导致交付周期越来越长,运维成本居高不下。我们必须做出改变。


技术选型与整体架构设计

技术选型与整体架构设计

我们选择了 Spring Cloud 全家桶来作为微服务框架的基础,因为:

  • 它与 Spring Boot 天然兼容,上手门槛低;
  • 提供了丰富的开箱即用组件(服务注册发现、负载均衡、配置中心等);
  • 社区活跃,文档丰富,遇到问题能找到答案。

架构图简述

整个微服务系统大概分为以下几个部分:

[ Gateway ]
   |
   |-----> [User Service]
   |
   |-----> [Product Service]
   |
   |-----> [Order Service]
   |
   |-----> [Config Server]
   |
   |-----> [Service Registry (Eureka)]

其中各组件的作用如下:

模块 功能描述
Eureka 服务注册与发现
Zuul / Gateway 请求路由,鉴权,限流
Config Server 集中管理各个服务的配置
Hystrix 服务熔断,防止雪崩
Sleuth & Zipkin 分布式日志追踪

缓存策略对比-1

接下来我会以其中一个子系统为例(比如订单服务),逐步展开具体的实现过程和关键代码。


代码实践:Spring Cloud 微服务搭建全过程

代码实践:Spring Cloud 微服务搭建全过程

这里展示的是我们搭建第一个微服务——订单服务的过程。

第一步:创建父项目 spring-cloud-demo

这个项目的职责是统一管理所有子模块依赖和版本。

<!-- pom.xml -->
<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>


![缓存策略对比-2](https://code-guide.oss.shanghai.autogptai.club/common/file/download?name=date2025062809/935b3448-e9ef-487d-a8b6-73ac2cda60dd.jpg)


    <dependencyManagement>
        <dependencies>
            <!-- 统一管理 Spring Cloud 版本 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2020.0.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

第二步:创建订单服务模块 order-service

这是一个标准的 Spring Boot 工程,加入 Spring Cloud Starter NetFlix 相关依赖即可注册到 Eureka 中。

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

对应的配置文件:

# application.yml
server:
  port: 8081
spring:
  application:
    name: order-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

启动之后访问 Eureka 控制台:http://localhost:8761/,就能看到订单服务成功注册进来了。

第三步:服务间调用与负载均衡(Feign + Ribbon)

订单服务需要调用用户服务获取用户信息:

@FeignClient(name = "user-service")
public interface UserServiceClient {
    @GetMapping("/users/{userId}")
    User getUserById(@PathVariable Long userId);
}

Feign 默认集成了 Ribbon,会自动实现客户端负载均衡。

第四步:加个网关(Gateway)

网关我们选择的是 Spring Cloud Gateway。

主类直接使用:

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

配置文件:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

这样外部请求就可以统一走 /api/xxx/xxx 进入对应服务。


实战中的踩坑经验分享

在实际开发过程中,我们遇到不少“小坑”,下面几个印象比较深的:

坑1:服务注册失败?看看防火墙!

初期部署时,服务总是注册不上。查了半天网络,最后发现是生产环境服务器禁用了默认的 8761 端口。解决方法就是在配置里明确指定:

eureka:
  instance:
    non-secure-port-enabled: true
    secure-port-enabled: false

坑2:Feign 不支持 GET 请求传 POJO?

有一次我们在 Feign 接口中用了一个复杂的对象做参数,结果报错。原来是 Feign 默认不支持 GET 方法传复杂对象参数(会被转成 URL 查询字符串)。建议的做法是改用 @SpringQueryMap 注解或改为 POST。

坑3:网关路径转发规则配置错误导致 404

在配置 Gateway 的时候没注意路径前缀匹配规则,有时候 /api/user 匹配不到 /api/user/123,后来改成使用通配符:

predicates:
  - Path=/api/user/**

坑4:多个服务实例共享数据库连接池

早期没用连接池时,服务一扩容就出现连接数打满数据库的情况。后来引入了 HikariCP,并根据并发量调整最大连接数:

spring:
  datasource:
    hikari:
      maximum-pool-size: 20

上线后的效果与收益总结

迁移完成后,我们的系统发生了明显的变化:

部署速度提升5倍以上:每个服务独立构建发布,不需要停机全量更新;
可用性更高:订单服务宕掉不会影响用户登录等功能;
可伸缩性强:高峰期能动态扩容特定服务节点;
团队协作更顺畅:各组负责各自的服务模块,代码冲突减少很多。

虽然微服务也带来了一些新的挑战(如服务监控、日志聚合、链路追踪等),但我们陆续引入了 Zipkin、Prometheus + Grafana 来解决问题。


给读者的几点建议

如果你正在考虑是否要使用 Spring Cloud 或者刚刚入门,这里有几个建议可以参考:

  1. 不要为了微服务而微服务:评估清楚当前项目是否真的需要拆分,避免过度设计。
  2. 重视基础设施建设:日志、监控、配置中心、熔断机制,这些才是微服务真正的护城河。
  3. 做好服务边界划分:前期多思考业务领域模型,避免后期服务之间频繁调用。
  4. 善用社区资源:Spring Cloud 社区非常活跃,很多问题都能找到现成的解决方案。
  5. 持续学习新技术:Kubernetes、Docker、Istio 等相关技术也在不断演进,掌握它们会让你更有竞争力。

结语:技术永远服务于业务,而我们要做的就是让服务更可靠

从最初的单体应用到如今的微服务体系,这一路上我们踩过坑、绕过弯、写错过不少代码,但也收获了许多宝贵的经验。

微服务不是银弹,但它确实在某些场景下解决了我们面临的实际问题。希望这篇真实的分享能够帮到正在学习 Spring Cloud 和微服务的朋友,少走一些弯路,更快地踏上通往高可用系统的道路。

如果你们也有类似的转型经历或者踩过什么特别大的坑,欢迎留言交流~技术这条路,从来都不是一个人在战斗。💪


本文内容基于笔者亲身经历撰写,如有雷同纯属巧合,请尊重原创。

评论 0

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