Nacos服务跨分组调用
一、 问题背景
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服务跨分组调用的更多相关文章
- ABP框架中微服务跨域调用其它服务接口
AjaxResponse为ABP自动包装的JSON格式 /// <summary> /// 通过地址和参数取得返回OutPut数据 /// </summary> /// < ...
- ThinkPHP实现跨模块调用操作方法概述
ThinkPHP实现跨模块调用操作方法概述 投稿:shichen2014 字体:[增加 减小] 类型:转载 使用 $this 可以调用当前模块内的方法,但是很多情况下经常会在当前模块中调用其他模块 ...
- ThinkPHP 跨模块调用操作方法(A方法与R方法)
ThinkPHP 跨模块调用操作方法(A方法与R方法) 跨模块调用操作方法 前面说了可以使用 $this 来调用当前模块内的方法,但实际情况中还经常会在当前模块调用其他模块的方法.ThinkPHP 内 ...
- AJAX跨域调用ASP.NET MVC或者WebAPI服务的解决方案
问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模板创建一个最简单的ASP.NET Web ...
- 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模 ...
- 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法
关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...
- 以短链服务为例,探讨免AppKey、免认证、Ajax跨域调用新浪微博API
新浪微博的API官方提供了很多种调用方式,支持编程的,归根结底就是两种: 1.基于Oauth协议,使用Open API.(http://open.weibo.com/wiki/%E6%8E%88%E6 ...
- Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)
原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问 ...
- AJAX跨域调用ASP.NET MVC或者WebAPI服务
关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案 作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP. ...
- SpringCloud使用Nacos服务发现实现远程调用
本文使用SpringCloud结合Nacos服务发现,Feign远程调用做一个简单的Demo. 1 Nacos 关于Nacos之前写了两篇文章关于SpringBoot对它的使用,感兴趣可以查看一下. ...
随机推荐
- 语义检索系统之排序模块:基于ERNIE-Gram的Pair-wise和基于RocketQA的CrossEncoder训练的单塔模型
语义检索系统之排序模块:基于ERNIE-Gram的Pair-wise和基于RocketQA的CrossEncoder训练的单塔模型 文本匹配任务数据每一个样本通常由两个文本组成(query,title ...
- C/C++中的可变参数和可变参数模板
目录 1.说明 2.C语言中的可变参数 3.C++中的可变参数模板 2.1.使用递归的方式遍历 2.2.使用非递归的方式遍历 1.说明 不谈官方定义,就从个人理解上说,可变参数 就是函数传参的时候,不 ...
- 基于AvaloniaUI开发跨平台.NET三维应用:环境搭建
本文介绍在Vistual Studio 2022中使用Avalonia和集成AnyCAD AvaloniaUI三维控件的的过程. 目录 0 初始化环境 1 创建项目 2 集成AnyCAD Avalon ...
- HP T520 改装DoraOS瘦客户机系统评测
HP T520 介绍 HP T520是一款瘦客户机产品.采用AMD GX-212JC 1.2 GHz 双核 SOC APU,带 AMD Radeon HD Graphics.配置4G 内存,8G SS ...
- (C语言)格式输出,右对齐
printf("%8d", i);可以输出整数 i,让它占至少 8 个字符的宽度(即场宽为8):如果 i 不够8 位则在左边补空格使它右对齐满 8 位,如果 i 的输出的位数 ≥ ...
- 逆天的全排列函数next_permutation()
next_permutation 是算法库(<algorithm>)里的一个用于求全排列的函数,其定义为 next_permutation(_BidIt _First, _BidIt _L ...
- 正则表达式,JSON.stringify() 去除 所有 key的下划线!!一句顶很多句。
最终的结论: JSON.stringify(userInfo).replace(/([{,]\")_(\w*\":)/g, "$1$2"); 开头锁定<以 ...
- IDEA中使用ChatGPT
IDEA中使用ChatGPT 在IDEA中安装ChatGPT插件,可以帮助写基础逻辑代码,提高工作效率和学习效率,有兴趣可以玩一下. 插件名为 Bito. 1. 什么是Bito Bito是一款在Int ...
- React axios 使用 http-proxy-middleware 解决跨域问题小记
壹 ❀ 引 在上篇bug分析的记录文中,提到axios可做到取消接口请求,所以想写一篇关于axios.CancelToken使用以及原理分析的文章(主要是自己好奇到底如何做到的取消).在准备工作阶段, ...
- 【framework】Activity启动流程
1 前言 ATMS启动流程 介绍了 ActivityTaskManagerService(ATMS)的启动和初始化流程,本文将介绍 Activity 的启动流程.由于 Activity 启动流程复杂, ...