1. 概述

Spring Cloud Consul 项目为 Spring Boot 应用提供了与 Consul 的无缝集成能力。

Consul 是一个解决微服务架构常见问题的工具集,核心功能包括:

  • 服务发现 - 自动注册/注销服务实例的网络位置
  • 健康检查 - 实时检测服务实例的可用性
  • 分布式配置 - 确保所有服务实例使用统一配置

本文将演示如何配置 Spring Boot 应用使用这些功能。

2. 前置准备

建议先快速了解 Consul 的核心特性。本文假设你已启动本地 Consul 代理(默认地址 localhost:8500)。安装指南可参考官方文档

首先添加 Maven 依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-all</artifactId>
    <version>3.1.1</version>
</dependency>

3. 服务发现

创建基础 Spring Boot 应用并连接 Consul:

@SpringBootApplication
public class ServiceDiscoveryApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ServiceDiscoveryApplication.class)
          .web(true).run(args);
    }
}

⚠️ 默认行为:Spring Boot 会自动尝试连接 localhost:8500 的 Consul 代理。如需自定义配置,修改 application.yml

spring:
  cloud:
    consul:
      host: localhost
      port: 8500

访问 http://localhost:8500 可看到应用已注册,默认 ID 格式为:
"${spring.application.name}:${profiles separated by comma}:${server.port}"

自定义注册 ID:

spring:
  application:
    name: myApp
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${random.value}

✅ 现在注册 ID 变为 myApp + 随机值,便于本地多实例测试。

禁用服务发现:设置 spring.cloud.consul.discovery.enabled=false

3.1. 服务查找

注册完成后,客户端如何发现服务?Spring 提供了 DiscoveryClient API:

@SpringBootApplication
@EnableDiscoveryClient
public class DiscoveryClientApplication {
    // ...
}

注入 DiscoveryClient 获取服务实例:

@RestController
public class DiscoveryClientController {
 
    @Autowired
    private DiscoveryClient discoveryClient;

    public Optional<URI> serviceUrl() {
        return discoveryClient.getInstances("myApp")
          .stream()
          .findFirst() 
          .map(si -> si.getUri());
    }
}

定义服务接口:

@GetMapping("/discoveryClient")
public String discoveryPing() throws RestClientException, 
  ServiceUnavailableException {
    URI service = serviceUrl()
      .map(s -> s.resolve("/ping"))
      .orElseThrow(ServiceUnavailableException::new);
    return restTemplate.getForEntity(service, String.class)
      .getBody();
}

@GetMapping("/ping")
public String ping() {
    return "pong";
}

关键点

  • Consul 通过 myApp 应用名返回所有可用实例
  • 路径 /ping 是服务端点,客户端通过 discoveryClient 动态发现

4. 健康检查

Consul 会定期检查服务端点健康状态。

默认行为:Spring 返回 /health 端点的 200 OK 状态。自定义检查路径需配置:

spring:
  cloud:
    consul:
      discovery:
        healthCheckPath: /my-health-check
        healthCheckInterval: 20s

现在 Consul 每 20 秒检查 /my-health-check 端点。

踩坑示例:返回 FORBIDDEN 状态

@GetMapping("/my-health-check")
public ResponseEntity<String> myCustomCheck() {
    String message = "Testing my healh check function";
    return new ResponseEntity<>(message, HttpStatus.FORBIDDEN);
}

此时 Consul 会显示服务状态异常。修复方法:确保端点返回 200 OK

5. 分布式配置

此功能实现跨服务配置同步:Consul 监听配置变更并通知所有服务更新。

添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-config</artifactId>
    <version>3.1.1</version>
</dependency>

⚠️ 重要:将 Consul 配置移至 bootstrap.yml(Spring 优先加载该文件):

spring:
  application:
    name: myApp
  cloud:
    consul:
      host: localhost
      port: 8500
      config:
        enabled: true

配置存储路径规则:/config/{applicationName}
例如属性 my.prop 需在 Consul 创建 Key:/config/myApp/my/prop,值设为 Hello World

多环境支持:使用 profile 时路径变为 /config/myApp,dev

控制器使用配置:

@RestController
public class DistributedPropertiesController {

    @Value("${my.prop}")
    String value;

    @Autowired
    private MyProperties properties;

    @GetMapping("/getConfigFromValue")
    public String getConfigFromValue() {
        return value;
    }

    @GetMapping("/getConfigFromProperty")
    public String getConfigFromProperty() {
        return properties.getProp();
    }
}

配置属性类:

@RefreshScope
@Configuration
@ConfigurationProperties("my")
public class MyProperties {
    private String prop;

    // standard getter, setter
}

✅ 启动后 valueproperties.prop 都会获取到 Hello World

5.1. 动态更新配置

如何不重启应用更新配置?

  1. 在 Consul 修改 /config/myApp/my/prop 值为 New Hello World
  2. 观察结果:
    • @Value 注入的 value 不会更新
    • MyProperties 类的 prop 自动更新

关键机制@RefreshScope 注解使 Bean 在配置变更时刷新。

⚠️ 生产环境建议:配置应持久化存储(如 Config Server),而非直接存在 Consul。

6. 总结

本文完整演示了 Spring Boot 与 Consul 的集成方案:

  1. 服务发现:自动注册与动态服务查找
  2. 健康检查:自定义检测规则与状态监控
  3. 分布式配置:跨服务配置同步与动态刷新

核心优势:通过 Consul 简化了微服务架构中的基础治理问题。完整代码示例见 GitHub


原始标题:A Quick Guide to Spring Cloud Consul