背景
還是先說下做這個的背景,開發環境上了K8S,所有的微服務都注冊在K8S內的Nacos,注冊地址為K8S內部虛擬IP,K8S內的服務之間相互調用沒有問題,但是本機開發聯調調用其他微服務就訪問不到。
解決方案
1、KT Connect,可以理解為一個VPN工具,可以和K8S網絡聯通,缺點是配置繁瑣,每次開發都需要啟動KT Connect程序;
2、配置Ribbon的listOfServers,配置如下:
<nacosServiceName>.ribbon.listOfServers=<ip:port>
3、Nacos Client從Nacos Server獲取服務列表時,修改遠程服務對應的IP地址。
重寫NacosNamingService
1、看了下nacos-client源碼,發現有個NacosNamingService類,主要是服務發現的實現類,可以從這里入手修改遠程服務注冊IP;
2、NacosNamingService是在NacosDiscoveryClientAutoConfiguration通過注入NacosDiscoveryProperties初始化的,具體源碼如下:
@Bean @ConditionalOnMissingBean public NacosDiscoveryProperties nacosProperties() { return new NacosDiscoveryProperties(); }
3、跟蹤到NacosDiscoveryProperties,初始化NacosNamingService的核心代碼如下:
public NamingService namingServiceInstance() { if (null != this.namingService) { return this.namingService; } else { Properties properties = new Properties(); properties.put("serverAddr", this.serverAddr); properties.put("namespace", this.namespace); properties.put("com.alibaba.nacos.naming.log.filename", this.logName); if (this.endpoint.contains(":")) { int index = this.endpoint.indexOf(":"); properties.put("endpoint", this.endpoint.substring(0, index)); properties.put("endpointPort", this.endpoint.substring(index + 1)); } else { properties.put("endpoint", this.endpoint); } properties.put("accessKey", this.accessKey); properties.put("secretKey", this.secretKey); properties.put("clusterName", this.clusterName); properties.put("namingLoadCacheAtStart", this.namingLoadCacheAtStart); try { this.namingService = NacosFactory.createNamingService(properties); } catch (Exception var3) { log.error("create naming service error!properties={},e=,", this, var3); return null; } return this.namingService; } }
4、我們直接重新namingServiceInstance方法就可以了,具體實現代碼如下:
@Slf4j @Configuration @ConditionalOnNacosDiscoveryEnabled @ConditionalOnProperty( name = {"spring.profiles.active"}, havingValue = "dev" ) @AutoConfigureBefore({NacosDiscoveryClientAutoConfiguration.class}) public class DevEnvironmentNacosDiscoveryClient { @Bean @ConditionalOnMissingBean public NacosDiscoveryProperties nacosProperties() { return new DevEnvironmentNacosDiscoveryProperties(); } static class DevEnvironmentNacosDiscoveryProperties extends NacosDiscoveryProperties { private NamingService namingService; @Override public NamingService namingServiceInstance() { if (null != this.namingService) { return this.namingService; } else { Properties properties = new Properties(); properties.put("serverAddr", super.getServerAddr()); properties.put("namespace", super.getNamespace()); properties.put("com.alibaba.nacos.naming.log.filename", super.getLogName()); if (super.getEndpoint().contains(":")) { int index = super.getEndpoint().indexOf(":"); properties.put("endpoint", super.getEndpoint().substring(0, index)); properties.put("endpointPort", super.getEndpoint().substring(index + 1)); } else { properties.put("endpoint", super.getEndpoint()); } properties.put("accessKey", super.getAccessKey()); properties.put("secretKey", super.getSecretKey()); properties.put("clusterName", super.getClusterName()); properties.put("namingLoadCacheAtStart", super.getNamingLoadCacheAtStart()); try { this.namingService = new DevEnvironmentNacosNamingService(properties); } catch (Exception var3) { log.error("create naming service error!properties={},e=,", this, var3); return null; } return this.namingService; } } } static class DevEnvironmentNacosNamingService extends NacosNamingService { public DevEnvironmentNacosNamingService(Properties properties) { super(properties); } @Override public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy) throws NacosException { List<Instance> instances = super.selectInstances(serviceName, clusters, healthy); instances.stream().forEach(instance -> instance.setIp("10.101.232.24")); return instances; } } }

