一、问题描述

我们现在是在用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注册中心不能够发现服务的问题解决相关推荐

  1. spring cloud集成nacos注册中心、配置中心、服务远程调用

    简介 Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos 帮助您更敏捷和容易地构建.交付和 ...

  2. 手动造轮子——为Ocelot集成Nacos注册中心

    前言 近期在看博客的时候或者在群里看聊天的时候,发现很多都提到了Ocelot网关的问题.我之前也研究过一点,网关本身是一种通用的解决方案,主要的工作就是拦截请求统一处理,比如认证.授权.熔断.限流.注 ...

  3. 【gateway系列】手把手教你gateway整合nacos注册中心

    目录 准备 Gateway服务 Member服务 运行 往期相关推荐: 网关路由规则和nacos配置中心实战: 一步步带你学习gateway路由规则实践 nacos整合配置中心 准备 准备引入相关依赖 ...

  4. 【Spring Cloud】Nacos注册中心

    文章目录 五.Nacos注册中心 5.1 认识和安装Nacos 5.2 服务注册到nacos 1)引入依赖 2)配置nacos地址 3)重启 5.3 服务分级存储模型 5.3.1 给user-serv ...

  5. Spring boot整合nacos注册中心/配置中心报错:java.lang.IllegalArgumentException: no server available

    1.问题描述 我是近期在使用Springboot整合nacos,由于springboot和springcloud都是用最新版本,啪的一下,很快啊,就出现问题了,于是自己把版本降下来了,年轻人不讲武德降 ...

  6. Spring cloud Alibaba Nacos注册中心(2) NacosNamingService

    NacosNamingService 文章目录 NacosNamingService 1.NamingProxy 2.BeatReactor 3.HostReactor 3.1 初始化 3.2 Fai ...

  7. Java行之有效的学习方法,Java直播课:Spring Cloud Alibaba Nacos 注册中心

    Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥 ...

  8. nacos注册中心(三)服务订阅

    Nacos监听服务 nacos监听服务,官方sdk资料:https://nacos.io/zh-cn/docs/sdk.html client端 NacosNamingService.subscrib ...

  9. 2:Alibaba微服务组件Nacos注册中心

    Spring Cloud Alibaba系列目录 提示:这里是第二章:Alibaba微服务组件Nacos注册中心 微服务和Spring Cloud Alibaba介绍 Alibaba微服务组件Naco ...

最新文章

  1. 关于CIC滤波器中积分器和梳状器的作用
  2. 数据恢复工具PhotoRec
  3. 思路:当一个表嵌套另一个表时候 只需在dao中引入该mapper即可 进行正常的数据插入 查询 修改等...
  4. slq2000数据库升级到sql2012
  5. 如何在面试中通过工厂模式来给自己加分?逆袭面经分享
  6. html 缩略图点击预览,[每天进步一点点~] uni-app 点击图片实现预览图片列表
  7. Verilog HDL设计实现m序列+选择器
  8. vConsole 让你在手机上也能轻松调试网页
  9. 报 There is insufficient memory for the Java Runtime Environment to continue. 的问题
  10. 页面自动刷新代码大全
  11. mac键盘符合对应含义(⌘ ⇧)
  12. 【软件设计师教程】程序设计语言基础知识
  13. 【Python学习】最新版pyecharts之绘制Map地图
  14. Java LocalDateTime给当前时间加半小时
  15. python中如何清空_python中如何清空数组(列表)元素
  16. BIM 360 二次开发入门
  17. Pycharm如何改变背景教程
  18. 今天烧了3个菜之一,炖豆腐
  19. 从移动互联网时代到物联网时代 梆梆安全追寻“本质安全”
  20. 编程语言静态/动态类型,强/弱定义分类以及七种程序错误类型

热门文章

  1. 7-5 手机号码 (20 分)
  2. rabbitmq高级特性(消息手动确认)
  3. golang设计模式——备忘录模式
  4. 今天科普一下 iOS马甲包审核以及常见审核问题
  5. linux如何初始化根文件系统,搭建自己的Linux根文件系统
  6. 01 基础入门:概念名词
  7. 最低仅需万元到手,Gooxi AMD Rome平台服务器特价啦
  8. 华为OD机试真题 Python 实现【机器人】【100%通过率】【2022.11 Q4 新题】
  9. 加载、编辑和保存Wod格式所见所得的Word文档处理控件TX Text Control ActiveX
  10. 助你掌握搜索神器,10个实用的Elasticsearch查询技巧