java的项目使用consul一般来讲都是通过spring-cloud-consul进行使用,spring-cloud帮助我们封装了consu的服务注册,服务发现等操作,但是在使用过程中还是出现了不少问题在这里记录下.
spring-cloud-consul在进行服务注册的时候会将我们的’spring.application.name’(服务名)+‘server.port’(端口号)注册到consul上源码如下图所示
因为使用的serverId相同,在consul上进行注册的时候会默认的将之前已经注册的服务覆盖掉
这种情况下需要人为的去重写spring-cloud-consul的bean更改在consul注册时的instanceId
这里在通过在yml中也可以进行指定instanceId但是为了统一处理所有的注册方法,进行bean的重写
在jar包中找到consul加载的方法
ConsulAutoServiceRegistrationAutoConfiguration.class
@Bean
@ConditionalOnMissingBean
public ConsulAutoRegistration consulRegistration(AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext applicationContext,
ObjectProvider> registrationCustomizers, HeartbeatProperties heartbeatProperties) {
return ConsulAutoRegistration.registration(autoServiceRegistrationProperties, properties,
applicationContext, registrationCustomizers.getIfAvailable(), heartbeatProperties);
}
追进去之后找到自动注册的bean,好在官方提供了@ConditationOnMissingBean这个注解,直接在外部生命bean就可以完成重写
@Bean
public ConsulAutoRegistration consulRegistration(AutoServiceRegistrationProperties autoServiceRegistrationProperties,
ConsulDiscoveryProperties properties, ApplicationContext applicationContext,
ObjectProvider> registrationCustomizers, HeartbeatProperties heartbeatProperties) {
properties.setHostname(IpAddrUtil.getLocalIP());
String appName = applicationContext.getEnvironment().getProperty("spring.application.name");
properties.setInstanceId(appName + "-" + serverProperties.getPort() + ":" + IpAddrUtil.getLocalIP());
return ConsulAutoRegistration.registration(autoServiceRegistrationProperties, properties,
applicationContext, registrationCustomizers.getIfAvailable(), heartbeatProperties);
}
这里将本机的ip和服务名称以及端口号进行组合传递到对象中.在进行服务注册的时候会直接使用get.InstanceId()进行获取
问题解决
服务注册的时候consul会对本机的健康检查接口进行调用,如果返回200则表示服务为Healthy Nodes 如果返回的请求有问题或者请求不通,则表示服务为Unhealthy Nodes 原因和上面的提到的情况类似,也可以通过重写服务注册的bean进行修改
spring-cloud在配置文件中同样提供了参数可以进行配置
但是问题关键在于,如果我们的服务处于docker中或者是虚拟机上时spring-cloud默认实现的ip获取会出现问题