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
}
✅ 启动后 value
和 properties.prop
都会获取到 Hello World
5.1. 动态更新配置
如何不重启应用更新配置?
- 在 Consul 修改
/config/myApp/my/prop
值为New Hello World
- 观察结果:
@Value
注入的value
不会更新MyProperties
类的prop
自动更新
关键机制:@RefreshScope
注解使 Bean 在配置变更时刷新。
⚠️ 生产环境建议:配置应持久化存储(如 Config Server),而非直接存在 Consul。
6. 总结
本文完整演示了 Spring Boot 与 Consul 的集成方案:
- ✅ 服务发现:自动注册与动态服务查找
- ✅ 健康检查:自定义检测规则与状态监控
- ✅ 分布式配置:跨服务配置同步与动态刷新
核心优势:通过 Consul 简化了微服务架构中的基础治理问题。完整代码示例见 GitHub。