项目场景:
使用Spring Cloud Alibaba使用Nacos作为注册中心,从order-service订单服务调用user-service用户服务。
启动两个服务,访问nacos的web控制台,两个服务均能正确注册到Nacos。
使用的Spring Cloud Alibaba版本:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Nacos版本: 2.0.0-BETA,运行在一台物理机上。
user-service和order-service运行在同一台物理机。与nacos不在一台机器,但在一个局域网内。
问题描述:
当在order-service中调用user-service中的接口时,出现如下错误:
2021-02-20 14:18:57.099 INFO 5292 --- [nio-8011-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client user-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=user-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@19ec1163
2021-02-20 14:18:57.135 ERROR 5292 --- [nio-8011-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for user-service] with root cause
java.lang.IllegalStateException: No instances available for user-service
at org.springframework.cloudflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:119) ~[spring-cloud-netflix-ribbon-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloudflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:99) ~[spring-cloud-netflix-ribbon-2.2.5.RELEASE.jar:2.2.5.RELEASE]
order-service调用user-service的代码:
@GetMapping("/order/create")
public String newOrder(long userId,String goodsId,int count){
Object user = restTemplate.getForObject("http://user-service/user/info?userId={userId}",
Object.class,
Collections.singletonMap("userId", userId));
System.out.println(user);
System.out.println("生成订单,商品id:"+goodsId+",数量:"+count);
return "ok";
}
原因分析:
首先排除法分析原因:
1、排除服务未成功注册到nacos,因为通过Nacos的web控制台可以看到已经成功注册服务。
2、排除RestTemplate类未加@LoadBalanced注解,再三确认RestTemplate Bean加了这个注解,此注解使用Ribbon进行服务调用负载均衡,通过上边的日志看出Ribbon是生效的。
3、通过Nacos提供的api,http://ip:8848/nacos/v1/ns/instance/list?serviceName=user-service,发现user-service服务列表为空,如下:
发现hosts为空,问题就出在这,服务从注册中心拉取其他服务的注册信息时,使用的就是这个接口,获取不到user-service的注册信息,在调用接口时Ribbon负责将url中的user-servicel替换成实例的ip地址和端口,发现没有该服务的实例,所以抛出了No instances available for user-service异常。同时查看上边的日志也可以看到这句:
DynamicServerListLoadBalancer for client user-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=user-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@19ec1163
这句日志是info级别的,一般情况谁会在意info级别的日志。仔细看发现current list of Servers=[],为空,和通过接口查询的结果一致。
根本原因找到了,是Nacos提供的拉取服务信息的接口返回的数据不对。
那到底是什么原因导致的这个问题?
解决方案:
仔细查看Nacos中注册的服务信息,发现注册的服务ip地址不对,如下图:
我本机的IP地址是192.168.0.104这个192.168.60.1哪来的?
执行ipconfig:
发现服务注册的ip使用了VMware的虚拟网络。没有使用192.168.0.104的局域网,相当于多块网卡,在进行服务注册时候,选中了VMware虚拟网络。
将服务注册的ip改成192.168.0.104这个,使Nacos和服务之间在一个网段,方法如下:
在服务的application.yml中,加入配置:
spring.cloud.inetutils: preferred-networks=192.168.0 #服务注册时优先使用这个网段。
重启服务,然后重试,一切OK!
调用Nacos的openAPI,http://192.168.0.105:8848/nacos/v1/ns/instance/list?serviceName=user-service
更多推荐
Spring Cloud 出现No instances available for user-service异常
发布评论