当我们的微服务优雅停机时,consul客户端会自动注销当前的微服务实例:
at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.deregister(ConsulServiceRegistry.java:86)
at org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry.deregister(ConsulServiceRegistry.java:41)
at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.deregister(AbstractAutoServiceRegistration.java:228)
at org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistration.deregister(ConsulAutoServiceRegistration.java:100)
at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.stop(AbstractAutoServiceRegistration.java:243)
at org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.destroy(AbstractAutoServiceRegistration.java:180)
Spring提供2种方式:实现DisposableBean接口或者使用@PreDestroy注解,用于应用程序退出时执行某些操作,比如释放资源等.
然而实际使用过程中,往往不是优雅停机的,这就导致了consul服务器上存在了一些不可用的微服务实例.
这里使用consul agent暴露的端点来手动注销这些不可用的微服务实例.
- List Checks端点,返回当前agent下注册的所有微服务实例以及相关检测信息
- Deregister Service端点:注销当前agent下的指定微服务实例
更多端点详见Agent HTTP API
部分代码:
@GetMapping("/deregister")
public String deregister() {
//由于自动注入的ConsulClient为当前微服务连接的consul agent,而注销的时候只能在微服务实例注册的agent下进行注销
//所以这里加了一个自定义的配置项配置consul集群地址 ip1:port1,ip2,ip3:port3.... 端口不配置默认8500
//读取并解析配置文件中配置的consul集群地址
Map<String, String> consulAddMap = this.getConsulAddress();
consulAddMap.forEach((host,port) -> {
//循环创建ConsulClient实例
ConsulClient client = new ConsulClient(host, Integer.valueOf(port));
//getAgentChecks 获取到当前agent下的所有注册的微服务实例
client.getAgentChecks().getValue().values().forEach(check -> {
//注销状态不为PASSING的微服务实例
if (!check.getStatus().equals(Check.CheckStatus.PASSING)) {
client.agentServiceDeregister(check.getServiceId());
}
});
});
return "OK";
}
代码详见github中的工程sc-learn-service-deregister
当然也可以手动注销某个微服务实例,比如:
PUT http://consulAgentIp:8500/v1/agent/service/deregister/微服务实例ID
参考文档
【程序猿DD】Consul注销实例时候的问题