当我们在Spring Cloud应用中使用Consul来实现服务治理时,由于Consul不会自动将不可用的服务实例注销掉(deregister),这使得在实际使用过程中,可能因为一些操作失误、环境变更等原因让Consul中存在一些无效实例信息,而这些实例在Consul中会长期存在,并处于断开状态,这些断开的实例有时候会影响服务的请求,所以我们需要删除这些无效的服务。所以这一篇注意来了解下如果出现无效的服务,我们怎么来注销掉这些无效的服务。下面是整理的consul的一系列的博文:

Consul1-window安装consul

Consul2-使用consul作为服务注册和发现中心

Consul3-使用consul作为配置中心

Consul4-linux安装consul以及集群搭建

Consul5-springboot2使用consul做为配置中心

Consul6-springboot2基于consul的服务调用

Consul7-注销掉consul无效服务

参考资料:

通过接口删除无效服务和节点:https://blog.csdn.net/harris135/article/details/77720686
通过代码删除无效服务:http://blog.didispace.com/consul-deregister/

 下面开始我们的正文吧!!!

一 删除consul的client节点

       我们知道consul分为server和client模式 ,一般我们在实际使用的时候应用是直接通过consul的client节点连接的,client节点会加入server节点同步server的一些基本数,实际请求时,client相当于一个转发的功能。当我们存在误操作的时候client节点挂掉了,但是在consul-ui界面还是可以看到这个节点,consul的ui界面没有提供删除这个client节点的功能,但是提供了api,我们可以通过提供的api来删除这个无效的client节点

linux下执行:eg:
     curl http://xx.xx.xx.xx:8500/v1/agent/force-leave/jack-client-dev
     jack-client-dev是client节点名称,名称可以通过类似这样的http://xx.xx.xx.xx:8500/ui/#/dc1/nodes路径查看,其实就是在consul的ui界面点击NODES
   http://xx.xx.xx.xx:8500 是consul的服务地址,ip加端口,或者域名

 

   二 删除consul无效的服务

     上面是删除无效的consul的client节点,这里是删除无效的consul服务,什么是consul无效的服务?比如我们使用spring cloud的时候,注册到consul上的服务,使用consul的服务注册与发现,那么注册到consul的服务我们在这里就说是consul的服务。当我们的服务挂掉了,但是consul-ui上还是可以看到这个服务,只是状态是falling的。如果有正常服务还有失败的服务,进行服务调用的时候,可能出现就会出现问题。这时候就需要删除这些无效的服务。consul同样提供了相关的api:

linux下执行:eg:

curl -X PUT http://xx.xx.xx.xx:8500/v1/agent/service/deregister/print-provider-10-10-112-21-9082-6dda57dbbdf15725e1d99bb57c7aff0e
 
http://xx.xx.xx.xx:8500是consul的服务地址
print-provider-10-10-112-21-9082-6dda57dbbdf15725e1d99bb57c7aff0e是服务id,可以通过http://xx.xx.xx.xx:8500/v1/agent/checks地址查看所有的服务

这时候可能有人会问了,什么是服务id,服务id就是使用springcloud的时候,我们的服务向consul注册的id,比如下面配置的instance-id就是这个服务的id:

server:
  port: 8082
spring:
  application:
    name: consul5
  cloud:
    consul:
    #配置consul服务器的host
      host: localhost
      #配置端口
      port: 8500
      config:
      #配置默认文件名
        default-context: ${spring.application.name}
        #是否启用consul配置
        enabled: true
        #配置文件格式
        format: YAML
        #配置基本文件,默认值config
        prefix: jack
        #配置文件名,默认data
        data-key: data
      discovery:
      #是否启用服务发现
        enabled: true
        #配置健康检查路径
        health-check-path: /actuator/health
        #配置健康检查时间间隔
        health-check-interval: 15s
        #配置实例id
        instance-id: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
        #配置服务注册
        register: true
        #服务停止时取消注册,http://www.imooc.com/article/286883?block_id=tuijian_wz
        deregister: true
        #表示注册时使用ip而不是hostname
        prefer-ip-address: true
        #健康检查失败多长时间取消注册
        health-check-critical-timeout: 30s
  profiles:
    active: dev

 

三  使用代码移除服务

上面第二步中我们删除根据服务id来删除服务,但是每次只能删除一个服务,但是实际中我们同一个服务名可能有多个服务id(每次启动服务都会重新生成一个服务id),难道每次都要一个一个删除这些无效的服务吗?这样太麻烦了,这里我们就可以使用代码来解决了,提供一个方法,输入服务名就可以删除这个服务名下所有的无效服务id了,eg:

@RestController
@RequestMapping("consul")
public class ConsulController {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConsulController.class);
    @Autowired
    private ConsulClient consulClient;
    @RequestMapping(value = "/deregister/{serviceNmae}",method = RequestMethod.POST)
    public ResponseResult deregisterService(@PathVariable String serviceNmae) {
        List<HealthService> response = consulClient.getHealthServices(serviceNmae, false, null).getValue();
        for(HealthService service : response) {
            // 创建一个用来剔除无效实例的ConsulClient,连接到无效实例注册的agent
            ConsulClient clearClient = new ConsulClient(service.getNode().getAddress(), 8500);
            service.getChecks().forEach(check -> {
                if(check.getStatus() != Check.CheckStatus.PASSING) {
                    LOGGER.info("unregister : {}", check.getServiceId());
                    clearClient.agentServiceDeregister(check.getServiceId());
                }
            });
        }
        return ResponseResult.success("移除"+serviceNmae+"成功");
    }

http://xx.xx.xx.xx:端口/consul/deregister/服务名

移除成功的返回信息,你们可以根据自己的定义。

比如我要删除consul5这个服务名,就可以这样调用这个接口了:

http://xx.xx.xx.xx:端口/consul/deregister/consul5

 

 

学习交流群:331227121

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐