由于Eureka宣告进入维护模式,所以抽空研究下Spring Cloud Consul做为服务注册中心。
此处不再赘述Consul原理、安装、使用等步骤,具体可以在网络查询,详细教程到处都是。主要描述下问题和解决方式:
问题描述
新建了一个微服务 service-a,从ip为【192.168.1.10】的机器启动,查看Consul一切正常,不关闭当前服务,再从ip为【192.18.1.20】的机器启动一个实例,查看Consul发现原来的注册实例还是只有一个,服务实例的ip地址被覆盖了;
分析解决
服务注册时,Consul是通过【instance-id】来区分服务实例的,出现服务实例注册被覆盖的情况,很有可能是因为多个实例【instance-id】重复导致。跟踪下源码,发现该字段默认是通过【application name】+ 【port】组成,所以服务注册会被覆盖;
解决方法1
通过查询官方文档,给出了解决方案:
By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is spring.application.name:comma,separated,profiles:{spring.application.name}:comma,separated,profiles:spring.application.name:comma,separated,profiles:{server.port}. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in spring.cloud.consul.discovery.instanceId.
将【instance-id】属性增加随机数,可以解决以上重复问题:
spring:
cloud:
consul:
discovery:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
解决方法2
通过查看类【HostInfoEnvironmentPostProcessor】,发现能够取到IP地址,可以改为以下方式:
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}
prefer-ip-address: true
解决方法3
通过扩展【ConsulServiceRegistry】类,自定义consul注册默认的实例名:
package com.irootech.config;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.discovery.TtlScheduler;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistry;
public class CustomConsulServiceRegistry extends ConsulServiceRegistry {
public CustomConsulServiceRegistry(ConsulClient client, ConsulDiscoveryProperties properties, TtlScheduler ttlScheduler, HeartbeatProperties heartbeatProperties) {
super(client, properties, ttlScheduler, heartbeatProperties);
}
@Override
public void register(ConsulRegistration reg) {
reg.getService().setId(reg.getService().getName() + ":" + reg.getService().getAddress() + ":" + reg.getService().getPort());
super.register(reg);
}
}
注入spring即可
package com.irootech.config;
import com.ecwid.consul.v1.ConsulClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.discovery.TtlScheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConsulServiceRegistryConfig {
@Autowired(required = false)
private TtlScheduler ttlScheduler;
@Bean
public CustomConsulServiceRegistry consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties, HeartbeatProperties heartbeatProperties) {
return new CustomConsulServiceRegistry(consulClient, properties, ttlScheduler, heartbeatProperties);
}
}
注意:使用这个方法无需在配置文件配置【instance-id】节点
版权声明:本文为CSDN博主「加斯特独挨踢」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangjin530/article/details/90911940