一、 问题背景

nacos有两种服务隔离的机制,一个是空间namespace,一般我们用namespace区分环境,另外一个是分组group,nacos的默认调用机制是同namespace下的同group的服务才可以相互调用;

那现在有个问题: 在测试阶段,由于测试环境和开发环境数据库等不一致,在测试出bug后,开发人员需要连接到测试环境上复线定位bug,但是如果开发人员本地启动测试环境,那么就会导致测试环境服务多了个本地的实例,这样测试在调用这个服务的时候很有可能就会访问这个本地服务,导致服务异常,所以一般我们都会采用本地服务自定义group分组的方式注册;

一般来说,一个服务关连多个其他服务,开发人员就需要把所有相关的服务都注册到自定义的group分组中,这样才能保证接口通常,但是起很多服务又会导致电脑内存消耗巨大,所以就想着能不能只启动存在问题的那个服务,其他关联服务还是使用测试环境的服务,基于这种考虑才想实现跨分组调用,减少无关服务的启动.

二、实现方案

1.版本要求

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.4.0</version>
</dependency>

如果 Java 项目的 nacos discovery 版本用的是 2021以上,则不需要重写 Ribbon 的负载均衡类,因为该版本的 Nacos 不依赖 Ribbon,只需要重写服务发现即可

2.重写服务发现

public class NacosServiceDiscoveryV2 extends NacosServiceDiscovery {

    public NacosServiceDiscoveryV2(NacosDiscoveryProperties discoveryProperties, NacosServiceManager nacosServiceManager) {
super(discoveryProperties, nacosServiceManager);
this.discoveryProperties = discoveryProperties;
this.nacosServiceManager = nacosServiceManager;
} private NacosDiscoveryProperties discoveryProperties;
private NacosServiceManager nacosServiceManager; // 重写该方法
public List<ServiceInstance> getInstances(String serviceId) throws NacosException {
String group = this.discoveryProperties.getGroup();
// 优先保证同分组下的服务调用
List<Instance> instances = this.namingService().selectInstances(serviceId, group, true);
if (CollUtil.isEmpty(instances)) {
// 如果同分组下找不到服务,那么就从默认分组下找服务
instances = this.namingService().selectInstances(serviceId, "DEFAULT_GROUP", true);
}
return hostToServiceInstanceList(instances, serviceId);
} public List<String> getServices() throws NacosException {
String group = this.discoveryProperties.getGroup();
ListView<String> services = this.namingService().getServicesOfServer(1, Integer.MAX_VALUE, group);
return services.getData();
} public static List<ServiceInstance> hostToServiceInstanceList(List<Instance> instances, String serviceId) {
List<ServiceInstance> result = new ArrayList(instances.size());
Iterator var3 = instances.iterator(); while (var3.hasNext()) {
Instance instance = (Instance) var3.next();
ServiceInstance serviceInstance = hostToServiceInstance(instance, serviceId);
if (serviceInstance != null) {
result.add(serviceInstance);
}
} return result;
} public static ServiceInstance hostToServiceInstance(Instance instance, String serviceId) {
if (instance != null && instance.isEnabled() && instance.isHealthy()) {
NacosServiceInstance nacosServiceInstance = new NacosServiceInstance();
nacosServiceInstance.setHost(instance.getIp());
nacosServiceInstance.setPort(instance.getPort());
nacosServiceInstance.setServiceId(serviceId);
nacosServiceInstance.setInstanceId(instance.getInstanceId());
Map<String, String> metadata = new HashMap();
metadata.put("nacos.instanceId", instance.getInstanceId());
metadata.put("nacos.weight", instance.getWeight() + "");
metadata.put("nacos.healthy", instance.isHealthy() + "");
metadata.put("nacos.cluster", instance.getClusterName() + "");
if (instance.getMetadata() != null) {
metadata.putAll(instance.getMetadata());
} metadata.put("nacos.ephemeral", String.valueOf(instance.isEphemeral()));
nacosServiceInstance.setMetadata(metadata);
if (metadata.containsKey("secure")) {
boolean secure = Boolean.parseBoolean((String) metadata.get("secure"));
nacosServiceInstance.setSecure(secure);
} return nacosServiceInstance;
} else {
return null;
}
} private NamingService namingService() {
return this.nacosServiceManager.getNamingService();
} }

3.重写自动配置类,更早的加载到Nacos容器中

@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureBefore({NacosDiscoveryAutoConfiguration.class})
public class NacosDiscoveryAutoConfigurationV2 { @Bean
@ConditionalOnMissingBean
public NacosServiceDiscovery nacosServiceDiscovery(NacosDiscoveryProperties nacosDiscoveryProperties, NacosServiceManager nacosServiceManager) {
return new NacosServiceDiscoveryV2(nacosDiscoveryProperties, nacosServiceManager);
}
}

其他版本的nacos的话,可能需要借助Ribbon负载均衡来处理跨分组调用,具体可参考以下:

参考:

Nacos服务跨分组调用的更多相关文章

  1. ABP框架中微服务跨域调用其它服务接口

    AjaxResponse为ABP自动包装的JSON格式 /// <summary> /// 通过地址和参数取得返回OutPut数据 /// </summary> /// < ...

  2. ThinkPHP实现跨模块调用操作方法概述

    ThinkPHP实现跨模块调用操作方法概述 投稿:shichen2014 字体:[增加 减小] 类型:转载   使用 $this 可以调用当前模块内的方法,但是很多情况下经常会在当前模块中调用其他模块 ...

  3. ThinkPHP 跨模块调用操作方法(A方法与R方法)

    ThinkPHP 跨模块调用操作方法(A方法与R方法) 跨模块调用操作方法 前面说了可以使用 $this 来调用当前模块内的方法,但实际情况中还经常会在当前模块调用其他模块的方法.ThinkPHP 内 ...

  4. AJAX跨域调用ASP.NET MVC或者WebAPI服务的解决方案

    问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模板创建一个最简单的ASP.NET Web ...

  5. 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案

      作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模 ...

  6. 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法

    关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...

  7. 以短链服务为例,探讨免AppKey、免认证、Ajax跨域调用新浪微博API

    新浪微博的API官方提供了很多种调用方式,支持编程的,归根结底就是两种: 1.基于Oauth协议,使用Open API.(http://open.weibo.com/wiki/%E6%8E%88%E6 ...

  8. Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)

    原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问 ...

  9. AJAX跨域调用ASP.NET MVC或者WebAPI服务

    关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案 作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP. ...

  10. SpringCloud使用Nacos服务发现实现远程调用

    本文使用SpringCloud结合Nacos服务发现,Feign远程调用做一个简单的Demo. 1 Nacos 关于Nacos之前写了两篇文章关于SpringBoot对它的使用,感兴趣可以查看一下. ...

随机推荐

  1. PE格式:VA地址与FOA地址

    PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如 ...

  2. [MySQL] 给root用户设置权限

    mysql> CREATE USER 'root'@'%' IDENTIFIED BY 'root'; mysql> GRANT ALL PRIVILEGES ON *.* TO 'roo ...

  3. TF-VAEGAN:添加潜在嵌入(Latent Embedding)的VAEGAN处理零样本学习

    前面介绍了将VAE+GAN解决零样本学习的方法:f-VAEGAN-D2,这里继续讨论引入生成模型处理零样本学习(Zero-shot Learning, ZSL)问题.论文"Latent Em ...

  4. C++ GDAL提取多时相遥感影像中像素随时间变化的数值数组

      本文介绍基于C++语言GDAL库,批量读取大量栅格遥感影像文件,并生成各像元数值的时间序列数组的方法.   首先,我们来明确一下本文所需实现的需求.现在有一个文件夹,其中包含了很多不同格式的文件, ...

  5. Kafka-基本介绍和常见问题

    1.kafka 1.1.kafka介绍 ​ kafka是最初由linkedin公司开发的,使用scala语言编写,kafka是一个分布式,分区的,多副本的,多订阅者的消息队列系统. 1.2.kafka ...

  6. NC20272 [SCOI2009]生日快乐

    题目链接 题目 题目描述 windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy ,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积 ...

  7. STM32F401CCU6与MFRC522接线及读取示例

    硬件准备 stm32f401ccu6最小开发板 rfid-rc522开发板 usb2ttl转接, 可以用pl2303, ch340, CP2102, FT232 Mifare 1K卡, UID长度4字 ...

  8. pico命令

    pico命令 pico是一个简单易用.以显示导向为主的文字编辑程序,具有pine电子邮件编写器的风格.在现代Linux系统上,nano即pico的GNU版本是默认安装的,在使用上和pico一模一样. ...

  9. Spring Boot图书管理系统项目实战-3.用户登录

    导航: pre:  2.项目搭建 next:4.基础信息管理 只挑重点的讲,具体的请看项目源码. 1.项目源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.登录页设计 <!DOCTYP ...

  10. Jsp+Servlet实现文件上传下载(三)--删除上传文件

    接着上一篇讲: Jsp+Servlet实现文件上传下载(二)--文件列表展示点击打开链接 本章来实现一下删除已上传文件,同时优化了一下第一章中的代码. 废话少说,上代码 --------------- ...