一、注册中心
1、pom.xml
在pom.xml 引入 spring-cloud-starter-consul-discovery 配置
<!-- consul 注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
2、启动类:SpringBootDemoApplication
在 SpringBootDemoApplication 上加上 EnableDiscoveryClient 注解
package com.example.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // consul 注册必须加上这个注解
public class SpringBootDemoApplication {
//@EnableAutoConfiguration注解通过@SpringBootApplication注解被间接的标记在了SpringBoot的启动类上,
// SpringApplicaton.run方法的内部就会执行selectImports方法,
// 进而找到所有JavaConfig配置类全限定名对应的class,然后将所有自动配置类加载到IOC容器中
public static void main(String[] args) {
//pringBootDemoApplication.class --> primarySource
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
3、配置文件
将application.yml 替换成 bootstrap.yml, 在 bootstrap.yml 加上注册中心的配置
server:
port: 8080
spring:
application:
name: spring-boot-demo
# profiles:
# active: dev # 指定环境,默认加载 default 环境
#================== consul 服务发现与注册中心配置 =======================#
cloud:
consul:
host: 1.116.43.223
port: 8500
#========注册中心==============
discovery:
instance-id: ${spring.application.name}:${server.port} #实例ID
health-check-path: /actuator/health #健康检测
service-name: ${spring.application.name} #服务名称
heartbeat:
enabled: true
health-check-critical-timeout: 60s #健康检测60s失败,取消注册
#========配置中心==============
config:
enabled: true # false禁用Consul配置,默认为true
format: YAML # 表示consul上面文件的格式,有四种:YAML、PROPERTIES、KEY-VALUE、FILES
prefix: config # 可以理解为配置文件所在的最外层目录
default-context: consul-service # 设置应用的文件夹名称
data-key: consul-service-config # Consul的Key/Values中的Key,Value对应整个配置文件
# 以上配置可以理解为:加载config/consul-service/文件夹下Key为consul-service-config的Value对应的配置信息
# 配置环境分隔符,默认值 "," 和 default-context 配置项搭配
# 例如应用 consul-service 分别有环境 default、dev、test、prod
# 只需在 config 文件夹下创建 consul-service、consul-service-dev、consul-service-test、consul-service-prod 文件夹即可
# profile-separator: '-'
watch:
enabled: true # 是否开启自动刷新,默认值true开启
delay: 1000 # 刷新频率,单位毫秒,默认值1000
运行效果
二、配置中心
1、pom.xml
在pom.xml 引入 spring-cloud-starter-consul-config 配置
<!-- consul 配置中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
2、配置文件
将application.yml 替换成 bootstrap.yml, 在 bootstrap.yml 加上注册中心的配置
server:
port: 8080
spring:
application:
name: spring-boot-demo
# profiles:
# active: dev # 指定环境,默认加载 default 环境
#================== consul 服务发现与注册中心配置 =======================#
cloud:
consul:
host: 1.116.43.223
port: 8500
#========注册中心==============
discovery:
instance-id: ${spring.application.name}:${server.port} #实例ID
health-check-path: /actuator/health #健康检测
service-name: ${spring.application.name} #服务名称
heartbeat:
enabled: true
health-check-critical-timeout: 60s #健康检测60s失败,取消注册
#========配置中心==============
config:
enabled: true # false禁用Consul配置,默认为true
format: YAML # 表示consul上面文件的格式,有四种:YAML、PROPERTIES、KEY-VALUE、FILES
prefix: config # 可以理解为配置文件所在的最外层目录
default-context: consul-service # 设置应用的文件夹名称
data-key: consul-service-config # Consul的Key/Values中的Key,Value对应整个配置文件
# 以上配置可以理解为:加载config/consul-service/文件夹下Key为consul-service-config的Value对应的配置信息
# 配置环境分隔符,默认值 "," 和 default-context 配置项搭配
# 例如应用 consul-service 分别有环境 default、dev、test、prod
# 只需在 config 文件夹下创建 consul-service、consul-service-dev、consul-service-test、consul-service-prod 文件夹即可
# profile-separator: '-'
watch:
enabled: true # 是否开启自动刷新,默认值true开启
delay: 1000 # 刷新频率,单位毫秒,默认值1000
3、consul 配置
根据 配置文件,新建对应的目录,并建好配置文件
三、consul 的自动注册
1、核心代码
package com.example.springbootdemo.config.consul;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* Created with IntelliJ IDEA.
*
* @Author: geek
* @Date: 2023/08/25/4:06 PM
* @Description:
*/
@Data
@Configuration
@ConfigurationProperties("spring.cloud.consul.retry")
public class ConsulRetryProperties {
/**
* 监测间隔(单位:ms)
*/
private long initialInterval = 10000L;
/**
* 间隔因子(备用)
*/
private double multiplier = 1.1D;
/**
* 最大间隔(备用)
*/
private long maxInterval = 20000L;
/**
* 重试次数(备用)
*/
private int maxAttempts = 6;
}
package com.example.springbootdemo.config.consul;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryClient;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Created with IntelliJ IDEA.
*
* @Author: geek
* @Date: 2023/08/25/4:09 PM
* @Description:
*/
@Configuration
@ConditionalOnClass({
ConsulDiscoveryClient.class,
ConsulAutoRegistration.class,
ConsulServiceRegistry.class
})
//@EnableConfigurationProperties(ConsulRetryProperties.class)
@Import({ConsulRetryProperties.class})
public class ConsulRetryAutoConfiguration {
// @Autowired
// private ConsulRetryProperties consulRetryProperties;
@Bean
@ConditionalOnMissingBean(ConsulRetryRegistry.class)
public ConsulRetryRegistry consulRetryRegistry(
ConsulAutoRegistration consulAutoRegistration,
ConsulServiceRegistry consulServiceRegistry,
DiscoveryClient discoveryClient,
ConsulRetryProperties properties
) {
return new ConsulRetryRegistry(
consulAutoRegistration,
consulServiceRegistry,
discoveryClient,
properties
);
}
}
package com.example.springbootdemo.config.consul;
import cn.hutool.core.thread.ThreadUtil;
import com.ecwid.consul.v1.agent.model.NewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @Author: geek
* @Date: 2023/08/25/4:14 PM
* @Description:
*/
@Slf4j
public class ConsulRetryRegistry implements CommandLineRunner {
private ConsulAutoRegistration consulAutoRegistration;
private ConsulServiceRegistry consulServiceRegistry;
private DiscoveryClient discoveryClient;
private ConsulRetryProperties properties;
public ConsulRetryRegistry(
ConsulAutoRegistration consulAutoRegistration,
ConsulServiceRegistry consulServiceRegistry,
DiscoveryClient discoveryClient,
ConsulRetryProperties properties
) {
this.consulAutoRegistration = consulAutoRegistration;
this.consulServiceRegistry = consulServiceRegistry;
this.discoveryClient = discoveryClient;
this.properties = properties;
}
@Override
public void run(String... args) {
// 获取当前服务
final NewService service = this.consulAutoRegistration.getService();
ThreadUtil.newSingleExecutor().execute(() -> {
log.debug("consul服务监测已启动【{}】", service);
while (true) {
try {
Thread.sleep(this.properties.getInitialInterval());
} catch (InterruptedException e) {
// 当前线程异常退出
log.error("consul服务已停止重新注册【{}】", service);
break;
}
// 健康检查
if (!checkStatus(service)) {
try {
// 重新注册
this.registry();
log.info("consul服务重新注册成功【{}】", service);
} catch (Exception e) {
log.warn("consul服务当前注册失败,准备下一次注册【{}】", service);
}
}
}
});
}
/**
* 服务注册
*/
private void registry() {
this.consulServiceRegistry.register(this.consulAutoRegistration);
}
/**
* 检查服务状态
*
* @param service 服务
* @return 返回布尔值,正常true,异常false
*/
private boolean checkStatus(NewService service) {
// 检测标志
boolean flag = false;
int existNum = 0;
try {
// 获取所有服务实例
List<ServiceInstance> instances = this.discoveryClient.getInstances(service.getName());
// 遍历实例
for (ServiceInstance instance : instances) {
// 判断是否为当前服务
if (instance.getInstanceId().equals(service.getId())) {
flag = true;
existNum++;
if (existNum>1){
log.info("consul服务心跳检测,注销多余注册的实例:{}",instance.getInstanceId());
this.deregister();
}
}
}
} catch (Exception e) {
}
log.debug("consul服务心跳检测结束,检测结果为:{}", flag ? "正常" : "异常");
return flag;
}
/**
* 服务取消注册
*/
private void deregister() {
this.consulServiceRegistry.deregister(this.consulAutoRegistration);
}
}
四、遇到的问题
1、config导致consul 配置host和port无效
解决方案1:
将 application.yml 替换成 bootsrap.yml
解法方案2:
因为安装网上的教程配置,发现都加这个配置,但是启动发现自己配置的host 和 port 无效
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
2、consul 删除无效节点服务
POST 调用 PUT 提交方式
http://1.116.43.223:8500/v1/agent/service/deregister/spring-boot-demo-8080
curl -X PUT http://127.0.0.1:8500/v1/agent/service/deregister/ocation-server-7101
参考文档:consul 删除无效节点服务