Spring Cloud 微服务:服务发现、配置与网关

FreeGuideOnline 最新 2026-06-17

Spring Cloud 微服务入门:服务发现、配置与网关

本教程面向微服务初学者,从零开始讲解 Spring Cloud 生态中最核心的三大基础设施:服务发现(Eureka)、分布式配置(Spring Cloud Config)和 API 网关(Spring Cloud Gateway)。你将通过可运行的代码示例快速掌握它们的配置与集成方式,为构建弹性、可维护的微服务体系打下坚实基础。

环境准备

  • JDK 17+
  • Maven 3.8+
  • Spring Boot 3.x + Spring Cloud 2022.0.x(与 Boot 3 兼容)
  • IDE(推荐 IntelliJ IDEA)
  • Git(供 Config Server 使用本地仓库测试时可选)

版本对齐:本教程使用 Spring Cloud 2022.0.4 (即 2022.0.x 版本),对应 Spring Boot 3.1.x。若使用 Spring Boot 2.x,建议使用 Spring Cloud Hoxton.SR12 或 2021.0.x 系列。


1. 服务发现:Eureka

1.1 什么是服务发现

在微服务架构中,服务实例的网络位置(IP 和端口)是动态变化的。服务发现机制允许服务之间通过逻辑名称而非硬编码地址进行通信。Eureka 是 Netflix 实现的服务注册与发现组件,包含两个角色:

  • Eureka Server:注册中心,维护所有服务实例的清单。
  • Eureka Client:服务提供方启动时向 Server 注册自己;服务消费方从 Server 获取服务列表,实现客户端负载均衡。

1.2 搭建 Eureka Server

新建 Spring Boot 项目,添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

主启动类添加 @EnableEurekaServer

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

application.yml 配置:

server:
  port: 8761
eureka:
  client:
    register-with-eureka: false  # 禁止Server注册自己
    fetch-registry: false
  server:
    enable-self-preservation: false # 开发环境关闭自我保护,方便测试

启动后访问 http://localhost:8761 看到 Eureka 控制台。

1.3 注册服务提供者

创建一个服务提供者(如用户服务),添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

启动类无需特殊注解(Spring Cloud 自动通过依赖检测注册),或者添加 @EnableDiscoveryClient 以示明确。 提供接口:

@RestController
public class UserController {
    @GetMapping("/user/{id}")
    public String getUser(@PathVariable String id) {
        return "User info for id: " + id + " from port:" + serverPort;
    }

    @Value("${server.port}")
    private String serverPort;
}

配置文件:

spring:
  application:
    name: user-service  # 服务名,极为重要
server:
  port: 8081
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

启动后,Eureka 控制台会显示 USER-SERVICE 实例。你可以复制该服务,用不同端口(8082、8083)启动多个实例,观察注册中心的效果。

1.4 服务消费者与负载均衡

消费者同样是一个 Eureka Client,并集成 Spring Cloud LoadBalancer(Spring Cloud 2020 后推荐代替 Ribbon):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

使用 RestTemplate@LoadBalanced 实现负载均衡:

@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/user/{id}")
    public String consumeUser(@PathVariable String id) {
        // 使用服务名代替 IP:Port
        String url = "http://user-service/user/" + id;
        return restTemplate.getForObject(url, String.class);
    }
}

启动消费者,多次访问 /consumer/user/1,会轮询到不同的 user-service 实例,证明负载均衡生效。

1.5 高可用与健康检查

  • 健康检查:默认 Eureka 通过心跳判断服务状态,服务端可配置 eureka.instance.lease-renewal-interval-in-seconds 控制心跳间隔。
  • 自我保护:生产环境应开启 eureka.server.enable-self-preservation=true,防止网络分区时误剔除健康实例。
  • 高可用:至少部署两个 Eureka Server 并互相注册,Client 配置多个 defaultZone 地址逗号分隔。

2. 分布式配置:Spring Cloud Config

2.1 为什么需要配置中心

微服务数量众多,分散管理配置耗时且易出错。配置中心将配置集中存储(Git、SVN、本地文件),服务启动时主动拉取,并支持运行时动态刷新。

Spring Cloud Config 分为:

  • Config Server:连接配置仓库,对外提供配置接口。
  • Config Client:从 Server 获取自身配置。

2.2 Config Server 搭建

新建项目,添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

启动类加 @EnableConfigServer

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

配置 application.yml

server:
  port: 8888
spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-repo/config-repo  # Git 仓库地址
          search-paths: '{application}'
          default-label: main
  # 若使用本地文件测试,可替换为:
  # profiles:
  #   active: native
  # cloud:
  #   config:
  #     server:
  #       native:
  #         search-locations: classpath:/config

在 Git 仓库中创建 user-service.yml(或 user-service-dev.yml):

server:
  port: 8081
my:
  custom: Hello from Config Server

验证:访问 http://localhost:8888/user-service/defaulthttp://localhost:8888/user-service/dev,应返回配置内容。

2.3 Config Client 接入

user-service 中增加 Config Client 依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- 动态刷新需要 actuator -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

bootstrap.yml(优先于 application.yml 加载):

spring:
  application:
    name: user-service
  cloud:
    config:
      uri: http://localhost:8888
      profile: dev  # 激活 profile
      label: main

将配置从 application.yml 迁移到 Git 仓库,本地只保留必需项(如 config 定位信息)。启动服务,会自动从 Config Server 拉取配置。

2.4 配置刷新与动态更新

当 Git 中配置变更时,客户端不需要重启即可刷新。在 Controller 上添加 @RefreshScope

@RefreshScope
@RestController
public class ConfigTestController {
    @Value("${my.custom}")
    private String customValue;

    @GetMapping("/custom")
    public String getCustom() {
        return customValue;
    }
}

修改 Git 仓库中的 my.custom 值并 commit,然后调用客户端刷新端点:

curl -X POST http://localhost:8081/actuator/refresh

再次访问 /custom 将返回新值。注意,生产环境通常结合 Spring Cloud Bus 广播刷新事件。


3. API 网关:Spring Cloud Gateway

3.1 网关的作用

网关作为系统统一入口,提供路由转发、协议转换、安全认证、流量控制、日志监控等功能。Spring Cloud Gateway 基于 Reactor 和 WebFlux,性能优于 Zuul 1.x,且支持灵活的断言(Predicate)与过滤器(Filter)模型。

3.2 创建 Gateway 服务

新建项目,添加依赖(不要引入 spring-boot-starter-web,因为 Gateway 基于 WebFlux):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

启动类无需特殊注解。 application.yml

server:
  port: 9000
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service  # 使用 Eureka 服务名
          predicates:
            - Path=/user/**
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

此时访问 http://localhost:9000/user/1,网关会将请求转发到 user-service/user/1 接口。lb:// 前缀表示启用负载均衡。

3.3 路由配置与断言

Gateway 通过 predicates 匹配请求,常用断言工厂:

  • Path=/api/**:路径匹配
  • Method=GET,POST:请求方法
  • Header=X-Request-Id, \d+:请求头匹配
  • Query=foo, \w+:查询参数
  • Cookie=name, value:Cookie 匹配

示例:

routes:
  - id: order-service
    uri: lb://order-service
    predicates:
      - Path=/order/**
      - Method=POST
      - Header=Content-Type, application/json

匹配所有 /order/** 且 POST 方法、Content-Type 为 JSON 的请求。

3.4 过滤器与限流

过滤器在请求前后执行处理,分为内置和自定义两种。

  • StripPrefix- StripPrefix=1 可去掉路径第一段,如 /user/1 转发时变为 /1
  • AddRequestHeader- AddRequestHeader=X-Custom, MyValue
  • RequestRateLimiter:需结合 Redis 实现令牌桶限流。

配置限流过滤器示例(需要添加 spring-boot-starter-data-redis-reactive 依赖):

spring:
  cloud:
    gateway:
      routes:
        - id: rate-limited-route
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                key-resolver: "#{@userKeyResolver}"
  data:
    redis:
      host: localhost

定义 KeyResolver Bean(按请求 IP 限流):

@Bean
public KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}

全局过滤器可跨路由生效,实现 GlobalFilter 接口添加日志、鉴权等逻辑。


4. 整合与最佳实践

将上述三个组件整合到一个微服务脚手架中,启动顺序:Eureka Server → Config Server → 业务服务(含 Gateway)。Gateway 自身也可以作为一个 Eureka 客户端,并从 Config Server 拉取路由配置,实现动态路由。

核心要点

  • 服务命名:全部小写,使用连字符分隔,与配置文件保持一致。
  • 健康检查:为所有服务添加 Actuator 依赖并暴露 health 端点,便于监控。
  • 配置分层:利用 Spring Cloud Config 的 profile 与环境管理,避免环境间硬编码。
  • 网关高可用:Gateway 同样部署多实例,前端用 Nginx 反向代理。
  • 安全加固:网关层统一处理跨域、限流、认证,减轻业务服务负担。

常见问题

  • 服务无法注册:检查 Eureka 服务端端口和路径,客户端 defaultZone 是否正确,网络是否互通。
  • 配置拉取失败:确认 Config Server 可用,bootstrap.yml 配置是否正确,仓库路径与分支标签。
  • 网关路由 404:检查路由断言是否匹配,服务是否在注册中心,lb:// 写法是否正确。

结语

通过本教程,你已掌握 Spring Cloud 微服务中服务发现、配置管理与 API 网关的核心配置和使用方法。这三者是生产就绪微服务架构的基石。建议后续继续学习熔断限流(Resilience4j/Sentinel)、链路追踪(Sleuth+Zipkin/SkyWalking)等内容,构建完整的云原生应用。