vlambda博客
学习文章列表

注册服务到nacos服务器报错:nacos failed to req API after all servers tried

背景

本地已经安装了nacos-server 1.4.1,使用了官方提供的注册服务实例【
https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example】,使用了注册服务NamingService的registerInstance方法,代码如下所示:

package com.alibaba.nacos.example.spring.boot.controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;;

@Controller
@RequestMapping("discovery")
public class DiscoveryController {

@NacosInjected
private NamingService namingService;

@Autowired
private ApplicationContext context;

@RequestMapping(value = "/beans", method = GET)
@ResponseBody
public List<String> beans() throws NacosException {
return Arrays.asList(context.getBeanDefinitionNames());
}

@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get() throws NacosException {
return namingService.getAllInstances("nacos.test.3");
}

@RequestMapping(value = "/register", method = GET)
@ResponseBody
public void register() throws NacosException {
namingService.registerInstance("nacos.test.3", "11.11.11.11", 8888, "TEST1");
namingService.registerInstance("nacos.test.3", "2.2.2.2", 9999, "DEFAULT");
System.out.println(namingService.getAllInstances("nacos.test.3"));
}
}

浏览器或者postman发送get请求:

http://127.0.0.1:8080/discovery/register

报错:

nacos failed to req API:/nacos/v1/ns/instance after all servers(127.0.0.1:8848) tried ...

问题追踪

第一步

debug源码,追踪到nacos-client发送请求:

    public void registerService(String serviceName, Instance instance) throws NacosException {

LogUtils.LOG.info("REGISTER-SERVICE", "registering service " + serviceName + " with instance:" + instance);

final Map<String, String> params = new HashMap<String, String>(8);
params.put(Constants.REQUEST_PARAM_NAMESPACE_ID, namespaceId);
params.put("ip", instance.getIp());
params.put("port", String.valueOf(instance.getPort()));
params.put("weight", String.valueOf(instance.getWeight()));
params.put("enable", String.valueOf(instance.isEnabled()));
params.put("healthy", String.valueOf(instance.isHealthy()));
params.put("metadata", JSON.toJSONString(instance.getMetadata()));
params.put("serviceName", serviceName);
params.put("clusterName", instance.getClusterName());

reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.PUT);
}

注意:请求方法是PUT,查询OpenApi【
https://nacos.io/zh-cn/docs/open-api.html】

注册实例:注册一个实例到服务。请求类型:POST

修改实例:修改服务下的一个实例。请求类型:PUT

有问题,可能跟client的版本有关。查询项目的pom.xml文件:

    <properties>
<nacos-discovery-spring-boot.version>0.2.1</nacos-discovery-spring-boot.version>
</properties>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>${nacos-discovery-spring-boot.version}</version>
</dependency>
</dependencies>

此处依赖的
nacos-discovery-spring-boot-starter版本为0.2.1,发布日期为Dec, 2018

最新版本为0.2.7,发布日期为Mar, 2020 【
https://mvnrepository.com/artifact/com.alibaba.boot/nacos-discovery-spring-boot-starter】

解决问题

使用
nacos-discovery-spring-boot-starter最新版本0.2.7,项目注册正常了!

拓展

nacos-server版本和
nacos-config-spring-boot-starter有一个兼容问题,那想知道目前的nacos-server1.4.1 支持的nacos-config-spring-boot-starter最低版本是哪一个呢?

我想到了从代码入手,查看nacos源码的提交记录 Dec, 2018~Mar, 2020,发现NamingProxy变化的时间点:


发现在2019-01-12 请求方法发生了改变

注册服务到nacos服务器报错:nacos failed to req API after all servers tried


即这个日期之后的版本都是ok的,

注册服务到nacos服务器报错:nacos failed to req API after all servers tried


0.2.2版本发布时间晚于2019-01-12,即0.2.2版本及以后版本都支持nacos-server1.4.1,使用测试验证,是ok的!调研注册请求
http://127.0.0.1:8080/discovery/register
后,立即调用获取实例请求
http://127.0.0.1:8080/discovery/get
获取实例如下:

[
{
"instanceId": "2.2.2.2#9999#DEFAULT#DEFAULT_GROUP@@nacos.test.3",
"ip": "2.2.2.2",
"port": 9999,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@nacos.test.3",
"metadata": {},
"instanceHeartBeatTimeOut": 15000,
"ipDeleteTimeout": 30000,
"instanceHeartBeatInterval": 5000
},
{
"instanceId": "11.11.11.11#8888#TEST1#DEFAULT_GROUP@@nacos.test.3",
"ip": "11.11.11.11",
"port": 8888,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "TEST1",
"serviceName": "DEFAULT_GROUP@@nacos.test.3",
"metadata": {},
"instanceHeartBeatTimeOut": 15000,
"ipDeleteTimeout": 30000,
"instanceHeartBeatInterval": 5000
}
]

再次拓展


nacos-discovery-spring-boot-starter版本0.2.1时最高支持nacos-server的哪个版本呢?

通过请求的形式:/nacos/v1/ns/instance,找到nacos-server处理请求的控制器InstanceController[nacos-naming模块] 。通过提交记录发现:


服务端的修改时间为2019-1-11,和客户端NamingProxy的修改时间一致[服务器的修改时间早于客户端时间一天]。


但通过尝试和github上打tag(
https://github.com/alibaba/nacos/tags)的时间看,发现并不一致。以实验为准,0.2.1支持nacos1.3.0.

总结

从代码上来看,nacos的升级没有考虑到兼容性;

官方文档也没有服务器端和客户端的匹对说明,这对产品的迭代升级不利。

故安装nacos的最好方式还是从github上clone下代码,选择一个分支自己打包server和client。安装包安装的方式可能会造成服务端和客户端不兼容问题。