一、 问题背景

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. FOG Project的 FOS 编译

    FOG Project系统是一个免费的开源计算机网络克隆和管理解决方案系统,与传统的Ghost有很大的不同,如果您是计算机维护管理人员,当有大量机器需要同时部署上线的时候FOG Project是一个可 ...

  2. 一次人脸识别ViewFaceCore使用的经验分享,看我把门店淘汰下来的POS机改成了人脸考勤机

    POS软件是什么?你好意思吗,还在用老掉牙的Winform. 门店被淘汰的POS机 销售终端--POS(point of sale)是一种多功能终端,把它安装在信用卡的特约商户和受理网点中与计算机联成 ...

  3. gcc-11/g++-11安装

    终端依次输入 sudo add-apt-repository ppa:ubuntu-toolchain-r/test #添加工具链存储库 sudo apt-get install gcc-11 #安装 ...

  4. Linux-find命令报错: missing argument to `-exec'

    报错提示:find: missing argument to `-exec' 今天写一个清理脚本,用到了find命令.本来是这么写的: find . -type f -mtime +7 -name & ...

  5. MySQL的CTE(公用表表达式)

    (一)概念 MySQL的CTE是在MySQL8.0版本开始支持的,公用表表达式是一个命名的临时结果集,仅在单个SQL语句(例如select.insert.delete和update)的执行范围内存在. ...

  6. JS Leetcode 155. 最小栈 题解分析

    壹 ❀ 引 本题来自LeetCode155. 最小栈,难度简单,题目描述如下: 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x ...

  7. JS Leetcode 690. 员工的重要性 题解分析

    壹 ❀ 引 本题来自LeetCode690. 员工的重要性,难度简单,题目描述如下: 给定一个保存员工信息的数据结构,它包含了员工 唯一的 id ,重要度 和 直系下属的 id . 比如,员工 1 是 ...

  8. Shell 特殊符号(变量)用法小结

    Shell | 特殊变量   $n 基本语法: $n (功能描述:n 为数字,$0 代表该脚本名称,$1-$9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}) 例如: ...

  9. tensorflow解决回归问题简单案列

    1 待拟合函数 noise服从均值为0,方差为15的正太分布,即noise ~ N(0,15). 2 基于模型的训练 根据散点图分布特点,猜测原始数据是一个二次函数模型,如下: 其中,a,b,c为待训 ...

  10. SpringBoot+MybatisPlus实现关联表查询

    1.说明 最近写代码用到了mybatisPlus涉及到关联表查询.需求是这样的: 我有一个专业表major其中有个字段是所属院系dept_id,我需要通过这个dept_id关联院系表departmen ...