Spring Cloud从零开始:微服务入门指南

Prometheus小骑士
2025-06-26 05:24
阅读 349

引言:为什么我们要用Spring Cloud?

引言:为什么我们要用Spring Cloud?

那会儿我们公司接了一个中型项目,业务逻辑复杂但时间又特别紧。系统一开始是单体架构,随着需求逐渐增多,开发效率明显变慢,部署频繁出问题,而且一改一个功能就容易把别的模块搞崩。老板一看不行啊,要拆!

于是我们就决定重构系统,采用Spring Cloud + Spring Boot的微服务架构方案。

这是一次从零开始的过程。作为一个后端工程师,我之前虽然学过一些Spring Cloud的知识,但真正落地做项目时才发现——知识和实践之间,真的差着十万八千里。

今天我就想结合自己的实战经历,和大家一起从头梳理一下怎么一步步用Spring Cloud搭建起一套微服务系统。希望这篇文章能帮刚接触微服务的你少走点弯路。


项目背景与技术选型原因

项目背景与技术选型原因

我们做的项目是一个企业内部的OA平台,包含审批、文档、权限管理等多个模块。初期团队只有5个人,没有成熟的微服务经验。

技术栈选择上,我们选择了以下主要技术:

  • Spring Boot 2.7:快速构建独立运行的微服务
  • Spring Cloud 2021.0.3:服务治理的核心框架
  • Nacos:作为注册中心和服务配置中心(相比Eureka更成熟,支持动态配置)
  • Feign / OpenFeign:远程调用
  • Gateway:网关路由
  • MySQL + MyBatis Plus:数据库操作
  • Redis:缓存
  • RabbitMQ:异步通信
  • Lombok + MapStruct:简化代码编写

之所以选这些,是因为当时社区活跃度高,文档齐全,适合中小团队上手。


搭建中的挑战与解决方案

搭建中的挑战与解决方案

第一个挑战:服务发现怎么做?

刚开始我们尝试用Eureka,但后来在一次压测中发现其在大规模服务下响应不稳定,且UI界面也相对老旧。最终换成了Nacos,体验好得多。

举个真实例子:我们有个订单服务需要调用库存服务,最开始用硬编码写接口地址,一旦库存服务换了IP或者加了节点,就得改代码重新上线,特别麻烦。

解决方案:

引入Nacos客户端,两个服务启动时自动注册到Nacos,使用OpenFeign进行服务间调用。

# application.yml 示例
spring:
  application:
    name: inventory-service # 服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # Nacos 地址
// FeignClient 接口定义
@FeignClient(name = "order-service")
public interface OrderServiceClient {
    @GetMapping("/orders/{id}")
    Order getOrderById(@PathVariable Long id);
}

这样,OrderService变动时不影响InventoryService,实现了服务间的解耦。


第二个挑战:多个服务如何共享配置?

早期我们每个服务都有单独的配置文件,维护起来太痛苦。特别是测试、预发、生产环境切换时,手动改一堆配置,很容易出错。

解决方法:使用Nacos Config

我们在Nacos中统一管理配置,不同环境创建不同的DataId。

例如:

  • data-id=application.yaml(公共配置)
  • data-id=application-dev.yaml(开发环境专用)

服务启动时通过bootstrap.yml加载配置:

# bootstrap.yml
spring:
  application:
    name: inventory-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        extension-configs:
          - data-id: application-dev.yaml
            group: DEFAULT_GROUP
            refresh: true

这样就可以做到一处修改多处生效,并且还能实时刷新配置(需配合@RefreshScope注解)。


第三个挑战:如何对外暴露统一接口?

前端访问的时候不能直接调各个服务,必须统一经过一个入口,这就需要一个API网关

我们选用了Spring Cloud Gateway。

# gateway 的 application.yml 配置示例
spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

这样所有对/api/order/**的请求都会被转发到order-service服务上。

同时我们还加上了限流、鉴权过滤器,防止恶意攻击或滥用接口。


项目中的关键代码片段分享

项目中的关键代码片段分享

微服务启动类示例

@SpringBootApplication
@EnableDiscoveryClient // 启动服务注册发现
public class InventoryApplication {
    public static void main(String[] args) {
        SpringApplication.run(InventoryApplication.class, args);
    }
}

网关鉴权逻辑片段(自定义Filter)

@Component
public class AuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token == null || !isValidToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    private boolean isValidToken(String token) {
        // 实际业务中可对接SSO或其他验证方式
        return token.equals("valid_token_example");
    }
}

踩坑经验:那些年我们一起掉过的“坑”

坑1:FeignClient默认不启用负载均衡

一开始我们发现Feign调用有时候只指向一台机器,不是负载均衡的,查了半天发现是没加spring-cloud-starter-loadbalancer这个依赖。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

加上之后才正常轮询。


坑2:Nacos宕机导致服务无法启动

有一次测试环境的Nacos挂了,结果微服务全部都启动不了,报错说找不到注册中心。这显然不符合预期,毕竟注册中心只是辅助作用。

解决办法:在Bootstrap.yml中配置健康检查回退机制,或者让服务容忍注册失败(需要定制实现)。最终我们在非关键环境中允许服务在无注册中心的情况下启动。


坑3:日志追踪混乱

微服务多了以后,日志分散在多个服务里,排查问题非常痛苦。比如用户提交了一个申请流程,涉及A→B→C三个服务,但我们没法直观看到整条链路的日志。

我们后来接入了Sleuth + Zipkin做分布式链路追踪。

简单提一句,只要引入下面的依赖即可开启链路追踪:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

再配个Zipkin Server,就能看到完整的请求链路了。


上线后的效果与收益总结

项目上线两个月后,我们做了个简单的评估:

维度 效果
部署效率 提升约40%:各服务可以独立部署,互不干扰
故障隔离性 明显提升:某个服务崩溃不会影响其他模块
开发协同 更高效:按业务划分模块,各自独立开发
运维难度 初期增加,后期降低:初期学习成本大,后期可通过K8s管理

其实最大的收益是架构上的灵活性。比如后续要做定时任务服务、消息推送服务,只需要新建一个新的微服务,不需要改动已有逻辑。

当然,也有遗憾的地方,比如我们并没有一开始就规划好数据分表策略,导致后面迁移数据结构时有些吃力。这也是一个值得反思的经验。


我的几点建议给新手朋友

  1. 别为了微服务而微服务
    如果业务量不大、开发人员不多,真的没必要上来就上微服务。否则你会陷入运维、部署、监控等一堆新问题。

  2. 提前设计好服务边界
    一定要基于业务来拆分服务,而不是技术。比如订单相关的放在一起,不要今天订单放在A服务,明天又移到B服务。

  3. 做好日志收集与链路追踪准备
    不然出了问题根本不知道哪里错了。Sleuth + Zipkin强烈推荐,甚至可以考虑ELK做日志聚合。

  4. 监控和报警不能少
    建议一开始就要加上Prometheus + Grafana来做服务指标监控,CPU、内存、QPS、延迟等都要看得到。

  5. 数据库设计要有前瞻性
    微服务下的数据库往往也是分开的,所以数据一致性是个大问题。要提前规划好哪些场景用分布式事务,哪些可以用最终一致性的手段处理。


最后一点小感悟

从最初的手忙脚乱到现在可以独立搭起一套Spring Cloud微服务架构,一路下来确实踩了不少坑。但也正是这些真实的项目实践,让我对后端系统的理解更深入了。

微服务从来不是一个银弹,它带来的不仅是架构的灵活性,还有运维、协作、排错等新的复杂性。所以,如果你正打算开始你的第一个微服务项目,我希望这篇文章能帮你少走些弯路。

最后送一句话给我自己,也送给每一位正在努力成长的技术人:

“真正的高手,不是掌握了多少工具,而是懂得何时用,怎么用。” —— 写给自己

感谢阅读,愿你在技术路上越走越稳。

评论 0

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