Spring Gateway集成 Nacos注册中心不能够发现服务的问题解决
一、问题描述
我们现在是在用Nacos替换Eureka,原来Eureka和Spring gateway运行正常,可以通过Spring gateway调用注册到Eureka中的服务。
当前Spring cloud的版本是Hoxton.SR8,Nacos discovery的版本为0.9.0.RELEASE,使用的Nacos版本为2.0.3。
Nacos替换Eureka改动的地方如下:
1、去掉POM中Eureka的引入;
2、去掉主类中引入的@EnableEurekaClient注解;
3、引入Nacos依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>0.9.0.RELEASE</version><exclusions><exclusion><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId></exclusion><exclusion><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>2.0.3</version>
</dependency>
4、引入spring-cloud-loadbalancer:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
5、spring-cloud-starter-openfeign中exclude掉ribbon的依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><exclusions><exclusion><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-netflix-ribbon</artifactId></exclusion></exclusions>
</dependency>
6、application.yml中禁用nacos的ribbon:
ribbon:nacos:enabled: false
现在的现象:
- Spring gateway启动不报错;
- gateway也可以正常注册到Nacos;
- 通过打断点到NacosDiscoveryClientAutoConfiguration,NacosDiscoveryClient会被初使化,但是调用时不会调用NacosDiscoveryClient.getInstances(String)获取被调用应用的Provider,会报类似下面的接口404错误:
{"msg":"/user-service/user/getByToken","result":404,"data":null}
其中user-service为注册到Nacos上面的服务名称,但是就是不能够被调用到。
- Spring gateway的注册中心切换为Eureka,再次调用服务时,Eureka的CompositeDiscoveryClient.getInstances(String)方法就会被调用。
二、问题分析
前面走了一些弯路,也花了一些时间,最后想到的是与Eureka注册中心进行对比调试分析,下面例出关键的分析步骤。
Debug断点打到DiscoveryClientRouteDefinitionLocator两个构造函数上,只有参数是ReactiveDiscoveryClient的构造函数被加载:
继续跟踪到ReactiveCompositeDiscoveryClient.getServices()方法:
发现数组变量discoveryClients包含了两个实现,如下图所示:
其中有一个是EurekaReactiveDiscoveryClient,那在使用Nacos时就应该包含一个针对Nacos实现的ReactiveDiscoveryClient,于是切换为Nacos分支调试。
但是调试发现数组变量discoveryClients并没有包含针对Nacos实现的ReactiveDiscoveryClient:
于是参考EurekaReactiveDiscoveryClient以及NacosDiscoveryClient,立即就写了NacosReactiveDiscoveryClient:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.NacosServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Flux;
/*** * @author fenglibin**/
@Slf4j
public class NacosReactiveDiscoveryClient implements ReactiveDiscoveryClient {public static final String DESCRIPTION = "Spring Cloud Nacos Reactive Discovery Client";private NacosDiscoveryProperties discoveryProperties;public NacosReactiveDiscoveryClient(NacosDiscoveryProperties discoveryProperties) {this.discoveryProperties = discoveryProperties;}@Overridepublic String description() {return DESCRIPTION;}@Overridepublic Flux<ServiceInstance> getInstances(String serviceId) {try {List<Instance> instances = discoveryProperties.namingServiceInstance().selectInstances(serviceId, true);return Flux.fromStream(hostToServiceInstanceList(instances, serviceId).stream());} catch (Exception e) {throw new RuntimeException("Can not get hosts from nacos server. serviceId: " + serviceId, e);}}@Overridepublic Flux<String> getServices() {try {ListView<String> services = discoveryProperties.namingServiceInstance().getServicesOfServer(1,Integer.MAX_VALUE);return Flux.fromStream(services.getData().parallelStream());} catch (Exception e) {log.error("get service name from nacos server fail,", e);return Flux.fromStream(Collections.<String>emptyList().stream());}}private static ServiceInstance hostToServiceInstance(Instance instance, String serviceId) {NacosServiceInstance nacosServiceInstance = new NacosServiceInstance();nacosServiceInstance.setHost(instance.getIp());nacosServiceInstance.setPort(instance.getPort());nacosServiceInstance.setServiceId(serviceId);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() + "");metadata.putAll(instance.getMetadata());nacosServiceInstance.setMetadata(metadata);if (metadata.containsKey("secure")) {boolean secure = Boolean.parseBoolean(metadata.get("secure"));nacosServiceInstance.setSecure(secure);}return nacosServiceInstance;}private static List<ServiceInstance> hostToServiceInstanceList(List<Instance> instances, String serviceId) {List<ServiceInstance> result = new ArrayList<>(instances.size());for (Instance instance : instances) {result.add(hostToServiceInstance(instance, serviceId));}return result;}}
或者集成如下starter:
<dependency><groupId>com.eeeffff</groupId><artifactId>nacos-reactive-discovery-client</artifactId><version>1.0.0</version></dependency>
并在启动时创建Bean:
再次启动调试就可以看到数组变量discoveryClients中有NacosReactiveDiscoveryClient了:
再次通过网关请求服务,就可以正常调用成功了。
感觉Nacos的怪问题都让我给碰上了!
Spring Gateway集成 Nacos注册中心不能够发现服务的问题解决相关推荐
- spring cloud集成nacos注册中心、配置中心、服务远程调用
简介 Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos 帮助您更敏捷和容易地构建.交付和 ...
- 手动造轮子——为Ocelot集成Nacos注册中心
前言 近期在看博客的时候或者在群里看聊天的时候,发现很多都提到了Ocelot网关的问题.我之前也研究过一点,网关本身是一种通用的解决方案,主要的工作就是拦截请求统一处理,比如认证.授权.熔断.限流.注 ...
- 【gateway系列】手把手教你gateway整合nacos注册中心
目录 准备 Gateway服务 Member服务 运行 往期相关推荐: 网关路由规则和nacos配置中心实战: 一步步带你学习gateway路由规则实践 nacos整合配置中心 准备 准备引入相关依赖 ...
- 【Spring Cloud】Nacos注册中心
文章目录 五.Nacos注册中心 5.1 认识和安装Nacos 5.2 服务注册到nacos 1)引入依赖 2)配置nacos地址 3)重启 5.3 服务分级存储模型 5.3.1 给user-serv ...
- Spring boot整合nacos注册中心/配置中心报错:java.lang.IllegalArgumentException: no server available
1.问题描述 我是近期在使用Springboot整合nacos,由于springboot和springcloud都是用最新版本,啪的一下,很快啊,就出现问题了,于是自己把版本降下来了,年轻人不讲武德降 ...
- Spring cloud Alibaba Nacos注册中心(2) NacosNamingService
NacosNamingService 文章目录 NacosNamingService 1.NamingProxy 2.BeatReactor 3.HostReactor 3.1 初始化 3.2 Fai ...
- Java行之有效的学习方法,Java直播课:Spring Cloud Alibaba Nacos 注册中心
Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥 ...
- nacos注册中心(三)服务订阅
Nacos监听服务 nacos监听服务,官方sdk资料:https://nacos.io/zh-cn/docs/sdk.html client端 NacosNamingService.subscrib ...
- 2:Alibaba微服务组件Nacos注册中心
Spring Cloud Alibaba系列目录 提示:这里是第二章:Alibaba微服务组件Nacos注册中心 微服务和Spring Cloud Alibaba介绍 Alibaba微服务组件Naco ...
最新文章
- 关于CIC滤波器中积分器和梳状器的作用
- 数据恢复工具PhotoRec
- 思路:当一个表嵌套另一个表时候 只需在dao中引入该mapper即可 进行正常的数据插入 查询 修改等...
- slq2000数据库升级到sql2012
- 如何在面试中通过工厂模式来给自己加分?逆袭面经分享
- html 缩略图点击预览,[每天进步一点点~] uni-app 点击图片实现预览图片列表
- Verilog HDL设计实现m序列+选择器
- vConsole 让你在手机上也能轻松调试网页
- 报 There is insufficient memory for the Java Runtime Environment to continue. 的问题
- 页面自动刷新代码大全
- mac键盘符合对应含义(⌘ ⇧)
- 【软件设计师教程】程序设计语言基础知识
- 【Python学习】最新版pyecharts之绘制Map地图
- Java LocalDateTime给当前时间加半小时
- python中如何清空_python中如何清空数组(列表)元素
- BIM 360 二次开发入门
- Pycharm如何改变背景教程
- 今天烧了3个菜之一,炖豆腐
- 从移动互联网时代到物联网时代 梆梆安全追寻“本质安全”
- 编程语言静态/动态类型,强/弱定义分类以及七种程序错误类型
热门文章
- 7-5 手机号码 (20 分)
- rabbitmq高级特性(消息手动确认)
- golang设计模式——备忘录模式
- 今天科普一下 iOS马甲包审核以及常见审核问题
- linux如何初始化根文件系统,搭建自己的Linux根文件系统
- 01 基础入门:概念名词
- 最低仅需万元到手,Gooxi AMD Rome平台服务器特价啦
- 华为OD机试真题 Python 实现【机器人】【100%通过率】【2022.11 Q4 新题】
- 加载、编辑和保存Wod格式所见所得的Word文档处理控件TX Text Control ActiveX
- 助你掌握搜索神器,10个实用的Elasticsearch查询技巧