Spring Cloud Consul集成
2026/1/15大约 4 分钟ConsulSpring Cloud微服务
Spring Cloud Consul 集成
一、概述
Spring Cloud Consul 提供了与 Consul 的无缝集成,支持服务发现、配置管理和分布式锁等功能。
1.1 核心功能
二、快速开始
2.1 添加依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 服务发现 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 配置管理 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<!-- Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>2.2 基础配置
# application.yml
spring:
application:
name: user-service
cloud:
consul:
host: localhost
port: 8500三、服务发现
3.1 启用服务发现
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}3.2 服务发现配置
spring:
cloud:
consul:
discovery:
enabled: true
service-name: ${spring.application.name}
instance-id: ${spring.application.name}:${random.value}
prefer-ip-address: true
ip-address: ${HOST_IP:localhost}
port: ${server.port}
health-check-path: /actuator/health
health-check-interval: 10s
tags:
- version=1.0.0
- env=dev
metadata:
zone: zone-a
weight: 103.3 使用 DiscoveryClient
@RestController
public class DiscoveryController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/services")
public List<String> getServices() {
return discoveryClient.getServices();
}
@GetMapping("/instances/{serviceName}")
public List<ServiceInstance> getInstances(@PathVariable String serviceName) {
return discoveryClient.getInstances(serviceName);
}
}四、服务调用
4.1 RestTemplate + LoadBalancer
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public User getUser(Long userId) {
return restTemplate.getForObject(
"http://user-service/users/" + userId,
User.class
);
}
}4.2 OpenFeign 集成
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") Long id);
@PostMapping("/users")
User createUser(@RequestBody User user);
}
@RestController
public class OrderController {
@Autowired
private UserClient userClient;
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable Long id) {
Order order = orderRepository.findById(id);
User user = userClient.getUser(order.getUserId());
order.setUser(user);
return order;
}
}4.3 WebClient 集成
@Configuration
public class WebClientConfig {
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
@Service
public class UserService {
@Autowired
private WebClient.Builder webClientBuilder;
public Mono<User> getUser(Long id) {
return webClientBuilder.build()
.get()
.uri("http://user-service/users/{id}", id)
.retrieve()
.bodyToMono(User.class);
}
}五、配置管理
5.1 Bootstrap 配置
# bootstrap.yml
spring:
application:
name: user-service
cloud:
consul:
host: localhost
port: 8500
config:
enabled: true
format: YAML
prefix: config
default-context: application
profile-separator: ','
data-key: data
watch:
enabled: true
delay: 10005.2 在 Consul 存储配置
# 公共配置
consul kv put config/application/data '
logging:
level:
root: INFO
'
# 服务配置
consul kv put config/user-service/data '
server:
port: 8080
user:
default-role: USER
'
# 环境配置
consul kv put config/user-service,dev/data '
user:
default-role: ADMIN
'5.3 使用配置
@RestController
@RefreshScope
public class ConfigController {
@Value("${user.default-role}")
private String defaultRole;
@GetMapping("/config/role")
public String getDefaultRole() {
return defaultRole;
}
}5.4 配置类绑定
@Configuration
@ConfigurationProperties(prefix = "user")
@RefreshScope
public class UserProperties {
private String defaultRole;
private int maxLoginAttempts;
private Duration sessionTimeout;
// getters and setters
}六、健康检查
6.1 配置健康检查
spring:
cloud:
consul:
discovery:
health-check-path: /actuator/health
health-check-interval: 10s
health-check-timeout: 5s
health-check-critical-timeout: 30s6.2 自定义健康指示器
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try (Connection conn = dataSource.getConnection()) {
return Health.up()
.withDetail("database", "connected")
.build();
} catch (SQLException e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
}七、负载均衡
7.1 Spring Cloud LoadBalancer
spring:
cloud:
loadbalancer:
ribbon:
enabled: false # 禁用 Ribbon7.2 自定义负载均衡策略
@Configuration
public class LoadBalancerConfig {
@Bean
public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
name
);
}
}7.3 基于权重的负载均衡
@Configuration
public class WeightedLoadBalancerConfig {
@Bean
public ServiceInstanceListSupplier weightedSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withWeighted()
.withCaching()
.build(context);
}
}八、分布式锁
8.1 使用 Consul Lock
@Service
public class DistributedLockService {
@Autowired
private ConsulClient consulClient;
public void executeWithLock(String lockKey, Runnable task) {
String sessionId = createSession(lockKey);
try {
if (acquireLock(lockKey, sessionId)) {
task.run();
}
} finally {
releaseLock(lockKey, sessionId);
destroySession(sessionId);
}
}
private String createSession(String name) {
NewSession session = new NewSession();
session.setName(name);
session.setTtl("30s");
return consulClient.sessionCreate(session, null).getValue();
}
private boolean acquireLock(String key, String sessionId) {
PutParams params = new PutParams();
params.setAcquireSession(sessionId);
return consulClient.setKVValue("locks/" + key, "locked", params).getValue();
}
private void releaseLock(String key, String sessionId) {
PutParams params = new PutParams();
params.setReleaseSession(sessionId);
consulClient.setKVValue("locks/" + key, "unlocked", params);
}
private void destroySession(String sessionId) {
consulClient.sessionDestroy(sessionId, null);
}
}九、服务网格
9.1 启用 Connect
spring:
cloud:
consul:
discovery:
register: true
connect:
enabled: true9.2 Sidecar 代理配置
{
"service": {
"name": "user-service",
"port": 8080,
"connect": {
"sidecar_service": {
"proxy": {
"upstreams": [
{
"destination_name": "order-service",
"local_bind_port": 9001
}
]
}
}
}
}
}十、生产配置
10.1 完整配置示例
spring:
application:
name: user-service
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev}
cloud:
consul:
host: ${CONSUL_HOST:localhost}
port: ${CONSUL_PORT:8500}
discovery:
enabled: true
service-name: ${spring.application.name}
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
health-check-path: /actuator/health
health-check-interval: 10s
health-check-critical-timeout: 30s
acl-token: ${CONSUL_ACL_TOKEN:}
tags:
- version=${APP_VERSION:1.0.0}
- env=${SPRING_PROFILES_ACTIVE:dev}
metadata:
zone: ${ZONE:default}
config:
enabled: true
format: YAML
prefix: config
default-context: application
profile-separator: ','
data-key: data
acl-token: ${CONSUL_ACL_TOKEN:}
watch:
enabled: true
delay: 1000
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: always