springcloud 里面常用的组件

Spring Cloud 不是一个单独的框架,而是一组围绕微服务落地的工程组件。它解决的不是某一个业务功能,而是微服务拆分之后必然出现的一组基础问题:服务在哪里、请求怎么进来、服务之间怎么调用、配置怎么管理、故障怎么隔离、链路怎么追踪。

如果把一个供应链系统拆成订单服务、库存服务、采购服务、仓储服务、结算服务,每个服务都可以独立部署和扩容。拆分之后的好处是边界清晰、扩展灵活,但随之而来的问题是系统从一个进程变成了多个进程的协作。Spring Cloud 常用组件就是为了处理这些协作问题。

Spring Cloud 常用组件协作流程

服务注册与发现:Eureka、Nacos、Consul

服务注册中心负责回答一个最基础的问题:服务在哪里。

在单体系统里,方法调用发生在同一个进程内,不需要知道网络地址。拆成微服务之后,订单服务调用库存服务,需要知道库存服务当前有哪些实例、实例的 IP 和端口是什么、哪些实例健康、哪些实例已经下线。

注册中心的工作方式通常是:

  1. 服务启动时,把自己的服务名、地址、端口、健康状态注册到注册中心。
  2. 服务运行期间,持续向注册中心发送心跳。
  3. 调用方从注册中心拉取可用实例列表。
  4. 注册中心根据心跳和健康检查剔除不可用实例。

Eureka 是 Spring Cloud 早期常用的注册中心,强调 AP 思路,在短时间网络抖动时更倾向于保证服务发现可用。Nacos 同时支持服务发现和配置管理,在国内项目里使用较多。Consul 提供服务发现、健康检查和 KV 存储,也常用于基础设施统一管理。

在供应链系统里,库存服务可能部署 6 个实例。订单服务不应该写死某一个库存服务地址,而是通过服务名 inventory-service 找到健康实例,再把请求分发过去。

配置中心:Spring Cloud Config、Nacos Config

配置中心负责回答另一个问题:配置怎么统一管理。

微服务数量多了以后,如果每个服务都把数据库地址、开关配置、限流阈值、第三方接口地址写在本地配置文件里,修改一次配置就要重新打包和发布多个服务,风险很高。

配置中心的工作原理是把配置从应用包里抽出来,集中存储和下发。服务启动时从配置中心读取配置,运行期间也可以通过刷新机制拿到最新配置。

典型配置包括:

  • 数据库连接信息。
  • Redis、MQ、搜索服务地址。
  • 业务开关,例如是否启用新的库存锁定策略。
  • 限流、超时、熔断阈值。
  • 不同环境的差异配置。

例如采购系统要临时关闭自动补货功能,只需要在配置中心修改 autoReplenish.enabled=false,再让采购服务刷新配置,不需要重新发布服务。

网关:Spring Cloud Gateway、Zuul

网关是微服务系统的统一入口。

如果没有网关,前端要直接知道订单服务、库存服务、报表服务、用户服务的地址,这会让前端和后端部署结构强耦合。网关把外部请求统一接进来,再根据路由规则转发到内部服务。

网关常见职责包括:

  • 路由转发:把 /api/orders/** 转发到订单服务。
  • 鉴权认证:统一校验 token、登录态、权限。
  • 限流降级:对高频接口做访问控制。
  • 日志审计:记录请求来源、耗时、状态码。
  • 协议适配:对外暴露统一 HTTP 接口,对内转发到多个服务。

Spring Cloud Gateway 基于响应式模型,性能和扩展性比早期 Zuul 1 更适合新项目。一个常见做法是把所有供应链后台请求都先打到网关,网关校验用户身份后,再转到订单、库存、采购等服务。

服务调用:OpenFeign、RestTemplate、WebClient

服务调用组件负责让一个服务更方便地调用另一个服务。

OpenFeign 的价值是把远程 HTTP 调用写得像本地接口调用。开发者只需要定义接口、声明服务名和路径,Feign 会根据服务发现结果、负载均衡策略和 HTTP 编码规则发起请求。

例如订单服务创建订单时,需要调用库存服务锁定库存:

1
2
3
4
5
@FeignClient(name = "inventory-service")
public interface InventoryClient {
@PostMapping("/inventory/lock")
LockResult lock(@RequestBody LockInventoryCommand command);
}

它背后的核心流程是:根据服务名找到实例列表,选择一个实例,组装 HTTP 请求,发送请求,解析响应,异常时交给重试、熔断或降级逻辑处理。

RestTemplate 是较早的同步 HTTP 客户端,WebClient 支持响应式调用。对于大多数普通业务服务,OpenFeign 的声明式调用更容易维护。

负载均衡:Ribbon、Spring Cloud LoadBalancer

负载均衡负责决定请求发给哪一个服务实例。

当库存服务有多个实例时,订单服务不能永远调用同一个实例,否则这个实例会成为热点。客户端负载均衡会从注册中心拿到实例列表,然后根据策略选择一个实例。

常见策略包括:

  • 轮询:请求依次分配给不同实例。
  • 随机:随机选择一个实例。
  • 权重:性能更强或权重更高的实例承担更多请求。
  • 最少连接或响应时间优先:尽量选择当前压力较小的实例。

Ribbon 是早期常见组件,新版本 Spring Cloud 更推荐 Spring Cloud LoadBalancer。它们的核心目标一致:让调用方不用关心某个服务具体部署了多少实例。

熔断与限流:Hystrix、Resilience4j、Sentinel

熔断和限流负责防止局部故障拖垮整个系统。

在分布式系统里,一个服务慢并不可怕,可怕的是调用它的服务都被拖慢。比如库存服务数据库异常,订单服务大量线程卡在库存锁定接口上,随后订单服务也无法响应,最终网关、前端和其他服务都受到影响。

熔断器的工作原理类似电路保护:

  1. 统计一段时间内的失败率、慢调用比例、异常数量。
  2. 当指标超过阈值时,打开熔断器。
  3. 熔断打开后,请求不再真实调用下游,而是直接失败或走降级结果。
  4. 过一段时间进入半开状态,放少量请求试探下游是否恢复。
  5. 如果试探成功,关闭熔断;如果失败,继续熔断。

Hystrix 曾经是 Spring Cloud 里最常见的熔断组件,但已经进入维护状态。新项目更常见的是 Resilience4j 或 Sentinel。Sentinel 在限流、热点参数控制、系统自适应保护方面更完整。

消息总线和消息驱动:Spring Cloud Bus、Stream

微服务之间不一定都要同步调用。对于不要求立即返回结果的业务,异步消息更适合。

Spring Cloud Stream 把消息中间件抽象成绑定模型,让业务代码不直接依赖 Kafka、RabbitMQ 等具体实现。Spring Cloud Bus 常用于配置刷新、服务间事件通知。

供应链系统里的典型场景是订单创建成功后发送 OrderCreatedEvent。库存服务订阅事件后扣减可售库存,仓储服务订阅事件后准备出库任务,积分服务订阅事件后累计客户积分。这样订单服务不需要同步等待所有下游服务完成。

异步消息的关键不是简单地把请求丢到 MQ,而是要处理幂等、重复消费、消息顺序、失败重试和最终一致性。

链路追踪:Sleuth、Zipkin、Micrometer Tracing

链路追踪负责回答线上排查时最痛苦的问题:一次请求到底经过了哪些服务,慢在哪里。

当用户点击创建采购单,可能经过网关、采购服务、供应商服务、库存服务、审批服务、消息队列。没有链路追踪时,只能分别查多个服务日志,很难把它们串起来。

链路追踪的工作方式是给每次请求生成 traceId,并在服务之间透传。每个服务再生成自己的 spanId,记录当前服务处理了什么、耗时多少、是否异常。Zipkin 或其他追踪平台负责收集和展示完整调用链。

Spring Cloud Sleuth 曾经负责自动注入 traceId 和 spanId。新版本生态里,Micrometer Tracing 是更主流的观测方案。

监控与治理:Actuator、Admin、Prometheus

服务能跑起来只是第一步,更重要的是知道它跑得怎么样。

Spring Boot Actuator 提供健康检查、指标、线程、环境变量等端点。Spring Boot Admin 可以集中查看服务状态。Prometheus 和 Grafana 常用于采集指标和展示监控面板。

供应链系统至少应该关注:

  • 接口成功率和 P95、P99 响应时间。
  • 数据库连接池使用率。
  • MQ 积压数量。
  • 服务实例健康状态。
  • 线程池队列长度。
  • 熔断、限流、降级次数。

总结

Spring Cloud 常用组件本质上是在处理微服务运行期治理问题。注册中心解决服务在哪里,配置中心解决配置如何统一,网关解决入口治理,Feign 解决服务调用,负载均衡解决实例选择,熔断限流解决故障隔离,消息组件解决异步解耦,链路追踪和监控解决可观测性。

真正落地时不要为了组件而组件。系统规模小的时候,可以先从注册中心、网关、配置中心、Feign、基础监控开始。等调用链复杂、流量变大、故障影响扩大时,再逐步引入熔断限流、链路追踪、消息驱动和更细的治理能力。