大爷的,弄了整整一天的时间,nacos注册中心就是不行。具体表现为 从nacos后台,服务管理-->服务管理,能看到生产者和消费已经注册上去了。但是,就是这个但是,可就是消费者通过restTemplate调用服务时,报错了。
这里先交待一下版本,spring-boot为2.4.6,springcloud为2020.0.3。
这里贴一下消费者的代码
spring-cloud-learn-nacos
org.example
1.0-SNAPSHOT
4.0.0
nacos-consumer
8
8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
application.properties
server.port=7000
spring.application.name=service-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
management.endpoints.web.exposure.include=*
启动类
package org.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApp {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApp.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
遇到的问题,用nacos作为注册中心,生产者和消费都注册进去了,但是,消费者调用服务时,报错
java.net.UnknownHostException: nacos-provider。
注意:我已经以注入了RestTemplate,并且使用了@LoadBalanced注解。
根据这个报错,有点基础的都能看到这是找不到主机。再结合最近接触eureka,zookeeper做为注册中心,都是这么一个写法,即 restTemplate.getForObject("http://service-provider/echo/name", String.class)。所以,怀疑是nacos配置的有问题(毕竟没用过,现在就是在研究怎么用nacos做为注册中心,所以初步怀疑是nacos哪里配置的不对。毕竟zookeeper做为注册中心研究成功了,还有另外一个原因,报错的代码,我可是从springcloud, springcloud alibaba, nacos上看到的,参考的,复制的)。经过查阅nacos资料,通过nacos提供的OPENAPI(http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos-provider
),发现能够获取到服务,所以,这里排除了nacos配置的问题。
下一步,把NACOS官方的示例,通过GIT弄下来吧(GitHub - nacos-group/nacos-examples: Nacos Examples)。现在是2021年9月,官网给出的示例,还是2年以前的东西了。下下来后,运行,试了一下,可以,能用,没有问题。这里指的是消费都够通过 restTemplate.getForObject("http://service-provider/echo/name", String.class)调用到服务方。
大爷的,那是哪的问题呢?根据最近的学习,知道可能跟ribbon有关(因为用它做客户端的负载均衡嘛,另外,如果是我自己写程序的完成调用服务方的话,无非就是把调用地址里的nacos-provicder,换成具体的目标IP,PORT呗,扯远了)。
经过细心排查,发现官网里手动的引了一个JAR,重点是还使用了版本号
官方示例里,发现注入了ribbon
官方里的springboot, springcloud版本号
Finchley.RELEASE
2.0.4.RELEASE
官网引入了ribbon
2.0.0.RELEASE
2.0.0.RELEASE
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
${spring-cloud-netflix.version}
org.springframework.cloud
spring-cloud-starter-openfeign
${spring-cloud-openfeign.version}
那就赶紧把 spring-cloud-starter-netflix-ribbon 这个依赖放到我项目里吧。运行后,依然报错。
这里我先卖个关子,其实到这里后,我的问题已经解决了。就像我前面说到的,我有弄过zookeeper做为注册中心,于是我看了下zookeeper做注册中心时,也没有特意的经入ribbon,并且项目上也没有ribboon的JAR。于是我解决的办法就是参考了一下zookepper做为注册中心时,引入的JAR包。到底怎么解决的,继续往下看吧。既然问题都解决了,为什么还要折腾?? 答案是:1、我就在想,我明明就是参照官网上的示例(包括springcloud,springcloud alibaba,nacos git上的代码),怎么我写的就不行呢,是不是哪里配置的不对了??? 2、我是不是瞎猫碰到死耗子了??
经过再一次排查,发现我的项目里,引入的spring-cloud-starter-netflix-ribbon依赖, 由于没有填写版本号,被坑了一下,以为SPRING-BOOT,SPRING-CLOUD里有这个依赖,已经有版本号了呢,这里我又要扯远了,我们都知道,SPRINGBOOT里集成了好多JAR,通常我们只需要填入groupId, artifactId这俩货就行了,可以不用写version,对吧,我没说错吧。所以我这里没填写version,所以我项目上没有到这个JAR,知道了原因,那就手工引入一下吧,胜利仿佛就在眼前了。加完入确认一下,项目里有这个 ribbon JAR了,再次运行程序,又换错误了。
No instances available for nacos-provider
我+++
对着代码调了半天,不知道为什么总是返回空。我+++。没办法了,换个想法,那就看下别人是怎么写的吧,于是,在gitee里,找下了一个别人的代码,试了一下,我的天,竟然可以。好吧,那我就分析下,我跟这个同志的代码有哪里不同,恩,他的版本没有我的高,换言之,我用的版本号是较新的。下面我贴出小同志的springboot, springbootcloud的版本号。
org.springframework.boot
spring-boot-starter-parent
2.2.10.RELEASE
Hoxton.SR8
于是,对比一下版本有个什么区别。最后发现,在spring-cloud-netflix-dependencies这个依赖里,截止到2.2.9REL里都包含了ribbon,可是,听我说,我的项目里,springcloud是
3.0.3
org.springframework.cloud
spring-cloud-netflix-dependencies
${spring-cloud-netflix.version}
pom
import
这里抛出一下问题,spring-cloud-netflix-dependencies 3.0后,为什么没有ribbon了???
突然想起一件事,好像是说netflix要闭源了,会不会是因为这个原因,springcloud里没有ribbon了??于是又是查资料,百度一下, 【netflix-ribbon 被取消 】 最后,找到了答案。
这里先写一下结论
Spring Cloud 2020.0正式发布,在这个主要版本里,spring-cloud-netflix-dependencies,只剩下eureka了,其它的全没有了。所以这也就是为什么,没有再导入ribbon了。所以那就是说,可以理解,不再支持ribbon了。
最后,给出这个问题该怎么解决,其实只需要在添加一个类似于ribbon的依赖就行了。ribbon在新版本里已经不再使用了,所以有个替代品。
添加一下下面的依赖就可以了。
org.springframework.cloud
spring-cloud-loadbalancer
顺便多说一下,就像我在前面提到的,我就是这么解决的,只不过当时心里没底,所以还在一直在坚持,坚持查原因,究竟是为什么???最后证实了确实是springcloud,netflix两家公司,神仙打架,导致spring放弃了netflix的支持(目前仅剩下netflix公司旗下的eureka了)。
如果没有我的坚持,我就不会发现是因为spring放弃了netflix。
就因为我的坚持,同时又了解到,springcloud以后的命名,将不再使用英文的城市命名。
我又想说一下,官网里的示例,controller里
@Autowired
private LoadBalancerClient loadBalancerClient;
我初次启动的时候,报错,没有注入这个BEAN。我+++,能不能靠谱点。
最后,贴一下消费者里的完整依赖。注意,我这里测试的是注册中心,不包括配置中心哦。
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-loadbalancer
写在最后吧,其实这个问题,从发生到解决,算上深夜还在调试,花了一天的时间来解决。这一天里疯了一样,一直在DEBUG,一直在查资料。还好总算是解决了。
在最后我想说一句,现在的贴子,版本号大多数还是较老的。就因为我用的是新版本,所以出了这么多问题,网上都找不到答案。哎。
参考资料
SpringCloud 2020版本教程0:springcloud 2020版本概述_方志朋的博客-CSDN博客
Spring Cloud 2020.0.0发布 再见了Netflix_吃透Java-CSDN博客
完美起航-SpringCloud2020.0.0正式发布,对开发者来说意味着什么?