使用Consul实现服务发现:instance-id自定义(3种方式)

TIPS

本文基于Spring Cloud Hoxton,理论支持Spring Cloud全部版本。html

本文探讨如何自定义微服务注册到Consul的InstanceId。java

Consul把InstanceId做为惟一标识,而Spring Cloud Consul默认的InstanceId是 ${spring.application.name}-${server.port}git

这样致使的问题是:某个微服务即便有多个实例,只要端口相同,那么Consul上依然只会保留1条数据!要想解决这个问题,只须要让不一样实例,拥有不一样的InstanceId便可。github

方式1:拼接随机值

添加配置:spring

spring:
  cloud:
    consul:
      discovery:
        instance-id: ${spring.application.name}-${server.port}-${random.long}

目前市面上的一些文章也是这么玩的。但这样作,在一些场景下仍是有一点小问题的。app

举个例子:假设某个微服务实例崩溃了,而后在很短的时间内(Consul还没来得及把这个实例删除);应用重启了,就会致使Consul上出现两条数据,但其实表明的是一个实例(虽然过段时间后,Consul会把没用的实例删除,但在一段时间内出现2条数据仍是很诡异的)。dom

TIPS

${random.long} 是Spring Boot自带的“扩展配置”,还有不少的使用姿式。文档可详见 https://docs.spring.io/spring...ide

方式2:拼接机器惟一标识


讲到这里,聪明的同窗必定会想到,一个合理的instanceid应该知足如下两点需求:spring-boot

  • 不一样实例的instanceid不一样;
  • 相同实例启动屡次,instanceid应该相同。

要想实现这两点诉求,只要在instanceid上加上机器的惟一标示就OK了,好比IP或者是主机名等等。微服务

spring:
  cloud:
    consul:
      discovery:
        instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.hostname}

或者:

spring:
  cloud:
    consul:
      discovery:
        instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address}
TIPS

这里,${spring.cloud.client.hostname} 以及 ${spring.cloud.client.ip-address} ,是利用了Spring Boot配置文件能够读取环境变量的特色。

你的应用只要集成Spring Boot Actuator ,就能够经过 /actuator/env 查看全部环境变量啦!环境变量的Key值,均可以写到配置文件中。

方式3:代码扩展

若是上面两种方式依然知足不了你的需求,那么你还能够经过写代码的方式去扩展。

代码:

public class WiiConsulAutoRegistration extends ConsulAutoRegistration {
    public WiiConsulAutoRegistration(NewService service, AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties, ApplicationContext context, HeartbeatProperties heartbeatProperties, List<ConsulManagementRegistrationCustomizer> managementRegistrationCustomizers) {
        super(service, autoServiceRegistrationProperties, properties, context, heartbeatProperties, managementRegistrationCustomizers);
    }
    
    public static String getInstanceId(WiiProperties wiiProperties,
                                       Environment environment) {
        return String.format("%s-%s-%s",
                environment.getProperty("spring.application.name"),
                wiiProperties.getIp(),
                wiiProperties.getPort());
    }
}

配置:

@Configuration
public class XXXConfiguration {
    @Bean
    public ConsulAutoRegistration consulRegistration(
            AutoServiceRegistrationProperties autoServiceRegistrationProperties,
            ConsulDiscoveryProperties properties,
            ApplicationContext applicationContext,
            ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,
            ObjectProvider<List<ConsulManagementRegistrationCustomizer>> managementRegistrationCustomizers,
            HeartbeatProperties heartbeatProperties) {
        return WiiConsulAutoRegistration.registration(autoServiceRegistrationProperties,
                properties, applicationContext, registrationCustomizers.getIfAvailable(),
                managementRegistrationCustomizers.getIfAvailable(), heartbeatProperties);
    }
}

TIPS

  • 这种方式更加灵活,你想怎么玩就怎么玩。你能够在InstanceId上拼接mac地址或者其余什么玩意儿……不过,只是为了定制个惟一标示而已,这么玩成本有点高了,我建议:若是没有不得已的苦衷,就甭折腾了
  • 个人我的项目 Spring Cloud Wii (也就是如今的Spring Cloud Alibaba Sidecar)就是使用的这种方式自定义InstanceId的。但Wii之因此采用这种方式,是由于Wii自己就要扩展 WiiConsulAutoRegistration ,定制一下InstanceId只是顺手而为。相关代码在这里,有兴趣能够看下: https://github.com/eacdy/spring-cloud-wii/blob/master/spring-cloud-wii/src/main/java/com/itmuch/wii/consul/WiiConsulAutoRegistration.java

将来...

将来若是这个Pull Request被合并,就不用折腾了……详见:https://github.com/spring-cloud/spring-cloud-consul/pull/570

本文首发

使用Consul实现服务发现:instance-id自定义

相关文章
相关标签/搜索