Skip to content

Spring Cloud 从零到生产级掌握

Spring Cloud 不是“会用 Feign 调接口”这么简单。它解决的是微服务拆分后的一整套协作问题:服务在哪里、请求走哪台机器、下游慢了怎么办、入口怎么统一、配置怎么统一、链路怎么追踪、老组件和新组件怎么对应。

一句话建立主线:

Spring Cloud 是微服务治理工具集。它把注册发现、远程调用、客户端负载均衡、网关路由、熔断限流、配置中心、链路追踪和消息事件组合成一套服务协作体系。

如果你想检查自己是否真的从零基础学懂到能面试、能落地、能排查,按 Spring Cloud 从零到精通验收清单 逐项验收。它把注册发现、Feign、LoadBalancer、Gateway、Sentinel、配置中心、链路追踪、商业场景和生产排查拆成可检查的问题。

学习目标

学完这一页,你要能做到:

  1. 解释 Spring Boot 和 Spring Cloud 的关系。
  2. 解释一次请求从 Gateway 到服务、从服务到服务的完整链路。
  3. 解释注册中心为什么需要心跳、缓存、健康检查和元数据。
  4. 解释 OpenFeign 为什么是接口代理,不是真正本地调用。
  5. 解释 Ribbon 和 Spring Cloud LoadBalancer 的关系。
  6. 解释 Gateway、Nginx、Ingress 的边界。
  7. 解释限流、熔断、降级、隔离、重试的差异和配合方式。
  8. 解释 Eureka、Ribbon、Hystrix、Zuul、Sleuth 和 Nacos、LoadBalancer、Sentinel、Gateway、Micrometer Tracing 的对应关系。
  9. 能把这些能力落到订单、支付、采集、库存、权限、接口聚合等商业场景里。

学习路线

mermaid
flowchart TD
    A["为什么拆微服务"] --> B["注册发现<br/>服务名到实例"]
    B --> C["远程调用<br/>OpenFeign/HTTP"]
    C --> D["负载均衡<br/>选择实例"]
    D --> E["网关入口<br/>路由鉴权限流"]
    E --> F["容错治理<br/>超时重试熔断降级"]
    F --> G["配置中心<br/>环境和动态配置"]
    G --> H["链路追踪<br/>traceId/span"]
    H --> I["生产排查<br/>超时、雪崩、调用失败"]

不要一上来背组件名。要先理解微服务拆分后产生了哪些问题,再看每个组件分别解决哪一类问题。

第一步:为什么需要 Spring Cloud

单体应用里,一个方法调用另一个方法:

java
orderService.createOrder(command);

它们在同一个 JVM 里,方法调用失败通常就是代码异常。

微服务拆分后,订单服务调用库存服务:

text
order-service -> stock-service

这就变成网络调用,会出现很多单体里没有的问题:

问题具体表现需要的治理能力
地址变化容器重启 IP 变了注册发现
多实例库存服务部署 5 台负载均衡
网络不稳定连接超时、读取超时超时、重试
下游慢上游线程被占满熔断、降级、隔离
外部入口多每个服务都暴露公网不安全网关
配置多每个环境配置不同配置中心
排查困难一次请求跨多个服务链路追踪

所以 Spring Cloud 不是为了“把系统拆散”,而是为了“拆散之后还能稳定协作”。

第二步:Spring Boot 和 Spring Cloud 的关系

对比项Spring BootSpring Cloud
关注范围单个服务如何快速开发、启动、运行多个服务如何注册、发现、调用、治理
典型能力自动配置、Starter、内嵌容器、Actuator注册中心、Feign、LoadBalancer、Gateway、Sentinel、配置中心
解决问题少写配置,快速构建一个应用服务之间稳定协作
关系基础建在 Spring Boot 之上

可以这样理解:

mermaid
flowchart TD
    A["Spring Framework<br/>IOC/AOP/事务"] --> B["Spring Boot<br/>自动配置和应用启动"]
    B --> C["Spring Cloud<br/>微服务治理"]

没有 Spring Boot,也可以做微服务;但 Spring Cloud 大量能力都是通过 Spring Boot 自动配置接入的,所以现代 Spring Cloud 项目通常建立在 Spring Boot 之上。

第三步:一次请求完整走法

典型商业系统链路:

text
客户端 -> Gateway -> order-service -> stock-service / user-service / pay-service
mermaid
flowchart TD
    A["客户端请求"] --> B["Gateway"]
    B --> C["鉴权、限流、日志、路由"]
    C --> D["lb://order-service"]
    D --> E["LoadBalancer 选择订单实例"]
    E --> F["订单服务"]
    F --> G["OpenFeign 调库存服务"]
    G --> H["注册中心获取库存实例"]
    H --> I["LoadBalancer 选择库存实例"]
    I --> J["HTTP Client 发请求"]
    J --> K["库存服务返回"]

这条链路里每个组件职责不同:

组件位置职责
Gateway外部入口路由、鉴权、限流、跨域、日志
注册中心基础设施保存服务名和实例列表
OpenFeign服务消费者内部把接口调用变成 HTTP 请求
LoadBalancer调用方内部从实例列表中选一个
Sentinel/Resilience4j调用前后限流、熔断、降级
Tracing全链路生成和传播 traceId/span

完整细节看 服务调用链路

第四步:注册中心原理

注册中心不是“微服务数据库”。它保存的是服务实例的运行时信息。

服务提供者启动后注册:

text
serviceName = stock-service
ip = 10.0.0.21
port = 8082
status = UP
metadata = version=v1, zone=shanghai

调用方按服务名发现:

text
stock-service -> [10.0.0.21:8082, 10.0.0.22:8082]
mermaid
flowchart TD
    A["服务启动"] --> B["注册 IP、端口、元数据"]
    B --> C["定期心跳续约"]
    C --> D["注册中心维护实例状态"]
    E["调用方"] --> F["按服务名获取实例列表"]
    F --> G["本地缓存实例"]
    G --> H["交给负载均衡选择"]

为什么需要心跳:

如果没有会怎样
无法知道实例是否还活着调用方可能一直打到宕机实例
无法自动剔除故障实例故障扩散到调用方
扩缩容后地址不同步新实例没流量,旧实例仍被调用

注册中心挂了还能不能调用:

  • 如果调用方本地有缓存,短时间内调用已有实例可能还能继续。
  • 新实例注册、旧实例剔除、配置变更、健康状态更新会受影响。
  • 生产上注册中心要高可用部署,客户端也要配置超时、熔断和本地缓存。

Eureka 更偏 AP,强调可用性;Nacos 同时支持注册发现和配置中心,支持命名空间、分组、元数据等能力。具体看 EurekaNacos

第五步:OpenFeign 原理

Feign 的核心不是“远程方法调用”,而是“接口代理 + HTTP 请求生成”。

java
@FeignClient(name = "stock-service")
public interface StockClient {
    @GetMapping("/stocks/{skuId}")
    Integer getStock(@PathVariable("skuId") Long skuId);
}

业务代码:

java
Integer stock = stockClient.getStock(1001L);

底层做了这些事:

mermaid
flowchart TD
    A["调用接口方法"] --> B["Feign 动态代理拦截"]
    B --> C["解析 @GetMapping 和参数"]
    C --> D["构造 HTTP 请求"]
    D --> E["按服务名找实例"]
    E --> F["负载均衡选实例"]
    F --> G["HTTP Client 发送"]
    G --> H["Decoder 反序列化响应"]

常见生产配置:

yaml
spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            connectTimeout: 2000
            readTimeout: 5000
            loggerLevel: basic

为什么必须设置超时:

超时类型含义不配置后果
connectTimeout建立连接等待多久目标不可达时长时间卡住
readTimeout请求发出后等响应多久下游慢时占满上游线程

写接口不要盲目重试。创建订单、扣库存、支付扣款如果没有幂等保护,重试可能导致重复业务动作。

第六步:负载均衡有哪些

Spring Cloud 常见负载均衡能力:

类型技术说明
客户端负载均衡RibbonNetflix 老组件,老项目常见
客户端负载均衡Spring Cloud LoadBalancer当前 Spring Cloud 官方推荐
服务端负载均衡Nginx、SLB、Ingress、Kubernetes Service调用方只访问统一入口

客户端负载均衡:

mermaid
flowchart TD
    A["order-service"] --> B["获取 stock-service 实例列表"]
    B --> C["本地选择一个实例"]
    C --> D["10.0.0.21:8082"]

服务端负载均衡:

mermaid
flowchart TD
    A["调用方"] --> B["Nginx/SLB/K8s Service"]
    B --> C["实例 1"]
    B --> D["实例 2"]
    B --> E["实例 3"]

常见算法:

算法原理适合场景
轮询依次选择实例实例规格接近
随机随机选实例简单通用
权重按权重分配机器规格不同、灰度
同区域优先优先同机房实例降低跨机房延迟
元数据路由按 version、tag 等选择灰度发布、多版本共存

如果某台机器压力特别大,要看:

  1. 实例权重是否不一致。
  2. 调用方实例列表是否过期。
  3. 是否有长连接或连接池集中打到某台。
  4. 是否某些请求被路由到固定实例。
  5. 是否调用方数量太少导致轮询不均。

第七步:Gateway、Nginx、Ingress 边界

组件更适合做什么不适合做什么
Nginx静态资源、反向代理、TLS、基础负载均衡深度理解微服务注册中心和业务鉴权
Gateway微服务路由、鉴权、限流、灰度、traceId复杂业务事务和领域规则
IngressKubernetes 集群入口路由复杂业务逻辑

Gateway 处理流程:

mermaid
flowchart TD
    A["请求进入 Gateway"] --> B["匹配 Route"]
    B --> C["Predicate 判断路径/方法/Header"]
    C --> D["GlobalFilter 执行"]
    D --> E["GatewayFilter 执行"]
    E --> F["lb:// 服务名解析"]
    F --> G["转发到后端服务"]

Gateway 适合放:

  • 登录态校验和基础鉴权。
  • 限流。
  • 黑白名单。
  • traceId 生成。
  • 请求日志。
  • 跨域。
  • 灰度路由。

不要放:

  • 下单事务。
  • 扣库存。
  • 数据库复杂查询。
  • 领域规则判断。

网关应该薄。业务规则应在对应服务里,否则网关会变成新的巨石应用。

第八步:限流、熔断、降级、重试怎么配合

这几个概念很容易混:

概念解决什么举例
超时不无限等下游读超时 5 秒
重试偶发失败再试一次查询接口超时重试 1 次
限流流量太大主动拒绝每秒最多 1000 请求
熔断下游明显异常时快速失败失败率 50% 打开熔断
降级失败后返回兜底推荐列表返回默认数据
隔离故障范围隔开独立线程池或信号量

正确顺序可以这样理解:

mermaid
flowchart TD
    A["请求进入"] --> B["限流判断"]
    B --> C["熔断器是否打开"]
    C --> D["发起远程调用"]
    D --> E["超时控制"]
    E --> F{"是否失败"}
    F -->|"否"| G["返回成功"]
    F -->|"是"| H["重试或记录失败"]
    H --> I["触发降级或抛异常"]

下游慢时只加重试会怎样:

mermaid
flowchart TD
    A["下游慢"] --> B["上游超时"]
    B --> C["上游重试"]
    C --> D["请求量被放大"]
    D --> E["下游更慢"]
    E --> A

所以生产建议:

  • 先设置合理超时。
  • 查询类接口可以少量重试。
  • 写类接口必须先做幂等,再考虑重试。
  • 下游失败率或慢调用比例高时熔断。
  • 入口或核心资源前限流。
  • 兜底结果必须符合业务正确性,不能假装支付成功或库存扣减成功。

第九步:配置中心怎么用

配置中心解决多服务、多环境配置管理问题。

适合放配置中心:

配置例子
业务开关是否开启某医院采集
阈值限流阈值、线程池大小
地址第三方接口地址
灰度版本开关、路由权重
非核心动态参数批处理大小、超时时间

不建议随便动态改:

  • 数据库核心连接信息。
  • 影响数据一致性的规则。
  • 密钥明文。
  • 没有审计和回滚的关键配置。

配置动态刷新不是万能的。动态配置要有默认值、校验、审计、灰度和回滚,否则一次错误配置可能让所有服务同时故障。

第十步:链路追踪和日志

微服务排查必须有 traceId。

mermaid
flowchart TD
    A["Gateway 生成 traceId"] --> B["请求头透传"]
    B --> C["order-service 日志打印 traceId"]
    C --> D["Feign 继续透传"]
    D --> E["stock-service 日志打印同一 traceId"]

核心概念:

概念含义
traceId一次完整请求的唯一 ID
spanId一段调用的 ID
parentSpanId上游调用段 ID
MDC把 traceId 放进日志上下文

老项目常见 Sleuth,新项目常见 Micrometer Tracing、OpenTelemetry、SkyWalking。组件可以变,但目标不变:把跨服务请求串起来,定位慢在哪一段、错在哪一段。

第十一步:新旧组件对比

治理能力经典 Netflix 体系当前常用方案是否必须学老组件
注册发现EurekaNacos、Consul、Eureka、Kubernetes老项目常见,建议理解
负载均衡RibbonSpring Cloud LoadBalancer要知道替代关系
熔断降级HystrixSentinel、Resilience4j要理解熔断思想
网关ZuulSpring Cloud GatewayZuul 老项目常见
链路追踪SleuthMicrometer Tracing、OpenTelemetry、SkyWalking要知道迁移方向
配置中心Spring Cloud ConfigNacos Config、Apollo、Config看公司选型

面试回答不要说“Ribbon 过时不用学”。正确说法是:

Ribbon 是 Netflix 老体系的客户端负载均衡组件,新项目更常用 Spring Cloud LoadBalancer。但两者解决的问题相同,都是从注册中心返回的实例列表里选择一个实例。理解 Ribbon 有助于理解老项目,理解 LoadBalancer 有助于做新项目。

商业项目场景

订单创建

text
Gateway -> order-service -> stock-service -> coupon-service -> pay-service

关键点:

  • Gateway 做鉴权、限流、traceId。
  • order-service 不能长时间等库存和支付。
  • 扣库存、支付必须幂等。
  • 写操作不能盲目重试。
  • 失败状态要落库,后续补偿。

医疗数据采集

text
采集调度 -> collect-service -> hospital-adapter-service -> asset-service

关键点:

  • 医院接口地址、采集开关、批大小放配置中心。
  • 外部医院接口慢时要超时、熔断。
  • 采集失败要记录批次和错误详情。
  • 资产同步 ES 可用消息异步化。
  • traceId 贯穿采集批次和子任务。

接口聚合

text
api-service -> user-service / asset-service / dictionary-service

关键点:

  • 聚合接口要减少循环 Feign 调用。
  • 下游查询尽量批量化。
  • 非核心展示字段可以降级。
  • 核心权限、金额、库存不能随便降级成功。

生产排查总流程

服务调用失败

mermaid
flowchart TD
    A["调用失败"] --> B["服务名是否正确"]
    B --> C["注册中心是否有实例"]
    C --> D["实例健康状态是否 UP"]
    D --> E["调用方本地缓存是否过期"]
    E --> F["网络和端口是否通"]
    F --> G["Feign 超时和错误日志"]
    G --> H["下游应用日志和 traceId"]

调用变慢

mermaid
flowchart TD
    A["接口变慢"] --> B["看 traceId 总耗时"]
    B --> C["定位慢 span"]
    C --> D["是网关慢还是服务慢"]
    D --> E["是 Feign 等待还是下游处理慢"]
    E --> F["查下游线程池、DB、缓存、外部接口"]

雪崩风险

现象可能原因处理
上游线程池满下游慢,Feign 等待超时、熔断、降级
下游 QPS 暴涨重试放大流量降低重试、退避、限流
某服务全部超时数据库慢或线程池耗尽查慢 SQL、线程栈、连接池
Gateway 502/504后端不可用或超时查路由、实例、超时、下游日志

最小 Demo

Feign Client

java
@FeignClient(name = "asset-service", fallback = AssetClientFallback.class)
public interface AssetClient {
    @GetMapping("/assets/{id}")
    AssetDTO getAsset(@PathVariable("id") Long id);
}

Fallback

java
@Component
public class AssetClientFallback implements AssetClient {
    @Override
    public AssetDTO getAsset(Long id) {
        return new AssetDTO(id, "unknown", "DOWNSTREAM_UNAVAILABLE");
    }
}

调用方

java
@RestController
@RequestMapping("/reports")
public class ReportController {
    private final AssetClient assetClient;

    public ReportController(AssetClient assetClient) {
        this.assetClient = assetClient;
    }

    @GetMapping("/{assetId}")
    public ReportVO report(@PathVariable Long assetId) {
        AssetDTO asset = assetClient.getAsset(assetId);
        return new ReportVO(assetId, asset.name(), asset.status());
    }
}

配置

yaml
spring:
  application:
    name: report-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    openfeign:
      client:
        config:
          default:
            connectTimeout: 2000
            readTimeout: 5000

这个 Demo 的重点不是“代码能写多复杂”,而是要看懂:接口代理、服务发现、负载均衡、HTTP 调用、超时和降级是怎么组合起来的。

面试标准回答

Spring Cloud 是什么

Spring Cloud 是微服务治理工具集,建立在 Spring Boot 之上,解决多个服务之间的注册发现、远程调用、负载均衡、网关路由、熔断限流、配置中心、链路追踪等协作问题。它不是单个组件,而是一套围绕服务稳定调用的治理体系。

服务调用链路怎么回答

服务提供者启动后把服务名、IP、端口和元数据注册到注册中心。调用方通过 OpenFeign 调接口时,Feign 代理会把接口方法解析成 HTTP 请求,再按服务名从注册中心拿实例列表,由 Spring Cloud LoadBalancer 选择一个实例,最后通过 HTTP Client 发请求。生产环境还要配合超时、重试、熔断、限流、降级和链路追踪,避免下游故障拖垮上游。

负载均衡有哪些

Spring Cloud 里常见客户端负载均衡,老项目是 Ribbon,新项目是 Spring Cloud LoadBalancer;入口层也常见 Nginx、SLB、Ingress、Kubernetes Service 这类服务端负载均衡。客户端负载均衡由调用方获取实例列表并本地选择实例,服务端负载均衡由统一代理层选择后端实例。

限流、熔断、降级区别

限流是流量太大时主动拒绝部分请求;熔断是下游失败率或慢调用比例过高时快速失败,防止继续打爆下游;降级是失败或熔断后返回可接受的兜底结果。它们通常和超时、重试、隔离一起使用。

关联知识点

本章小结

Spring Cloud 要按治理问题学习,而不是按组件名背诵。注册中心解决服务地址变化,OpenFeign 解决声明式 HTTP 调用,LoadBalancer 解决实例选择,Gateway 解决统一入口,Sentinel/Resilience4j 解决故障保护,配置中心解决配置管理,链路追踪解决跨服务排查。把这些能力串成一条请求链路,才算真正理解 Spring Cloud。