本文主要将使用旧版本Spring Cloud 2.0.0.RELEASE整合新版本Nacos2.2.3遇到的问题进行了记录。过程中共遇到两个问题,一个是Nacos2.1.X引入了鉴权导致的,另外一个是Spring Cloud Alibaba代码兼容问题。
Spring Cloud 2.0.0.RELEASE是一个比较老的版本,其中Spring Cloud Alibaba对应额Nacos的版本只到1.1.1,不过公司大部分项目都是基于Spring Cloud 2.0.0.RELEASE,需要研究一下老版本Spring Cloud使用最新版本Nacos的可行性。
在nacos官方文档中有明确关于兼容性的描述。
Nacos2.0的服务端完全兼容1.X客户端。Nacos2.0客户端由于使用了gRPC,无法兼容Nacos1.X服务端,
请勿使用2.0以上版本客户端连接Nacos1.X服务端。
同时也有关于Spring Cloud相关的描述。
可通过指定nacos-client方式,提前使用Nacos2.0长连接功能
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
2.1.5.RELEASE
com.alibaba.nacos
nacos-client
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
2.1.5.RELEASE
com.alibaba.nacos
nacos-client
com.alibaba.nacos
nacos-client
2.1.1
通过排除旧版本Spring Cloud对Nacos客户端依赖,引入最新的Nacos客户端版本就可以使用。
文档地址
通过官方文档的这两段描述明确了两点:
初一看在Spring Cloud 2.0.0.RELEASE使用最新版本Nacos 2.2.3完全没有问题。
按照官网的说明,安装Nacos服务端集群,配置Spring Cloud 2.0.0.RELEASE引入最新版本的客户端。但是启动后报错如下:
http error, code=403,msg=user not found
用户没有找到,猜想应该是和Nacos新版本中增加了鉴权的原因。去GitHub上搜了一把,发现也有人遇到这个问题。issues地址官方给的回答可能是版本不匹配。
在网上也有关于这个问题的博客,解决方法也是换版本。但是公司的Spring Cloud版本修改是一个比较重的操作,只能降低Nacos的版本。不过还是想通过源码能不能解决问题,发现配置中的下面这两个配置没有生效。在低版本的Spring Cloud Alibaba对应的配置类com.alibaba.cloud.nacos.NacosConfigProperties
中没有这两个成员变量。
spring.cloud.nacos.config.username=
spring.cloud.nacos.config.password=
在新版本客户端中有一个登录com.alibaba.nacos.client.auth.impl.NacosClientAuthServiceImpl#login
的操作,来换取accessToken,其中有下面这一段代码。
params.put(PropertyKeyConst.USERNAME, properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY));
bodyMap.put(PropertyKeyConst.PASSWORD, properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY));
由于旧版本的NacosConfigProperties
并没有这两个成员变量所以配置了也无法获取到值,服务器就返回了user not found
。用户鉴权毕竟是Nacos2.1.X才引入的。到这里可能就只有修改版本这条路了,但是断点查看properties发现里面居然有一百多个键值对,除了包含NacosConfigProperties
中的几个成员变量外,还有系统环境变量和JVM启动变量,那NacosConfigProperties
中没有username和password的问题就可以通过设置环境变量或者添加JVM启动变量来解决。
为了方便可以先在代码启动类中添加如下代码来测试。
System.setProperty(PropertyKeyConst.USERNAME, "nacos");
System.setProperty(PropertyKeyConst.PASSWORD, "nacos");
添加以后发现还是报错,但是报错的信息变成了404,不是之前的403。
在com.alibaba.cloud.nacos.NacosConfigProperties#configServiceInstance
中有一段这样的代码:
如果contextPath为null,就将他设置为空字符串。
properties.put(CONTEXT_PATH, Objects.toString(this.contextPath, ""));
在com.alibaba.nacos.client.auth.impl.process.HttpLoginProcessor#getResponse
中有下面这段:
String contextPath = ContextPathUtil.normalizeContextPath(
properties.getProperty(PropertyKeyConst.CONTEXT_PATH, webContext));
其实分开看都没有问题,但是合并到一起就有问题了。在Spring Cloud Alibaba中设置CONTEXT_PATH
时,如果为null,就设置为空字符串,但是在Nacos客户端使用时,如果不为null就设置为webContext
也就是/nacos
。所以这里如果不自己手动设置spring.cloud.nacos.config.context-path
就永远都为空字符串。URL中就没有/nacos
这一段,所以就会出现404了。 知道问题了,要解决就比较容易。
解决这个地址404的问题比较简单,因为低版本的Spring Cloud支持配置CONTEXT_PATH
,只要的bootstrap.propeprties
中配置spring.cloud.nacos.config.context-path=/nacos
就可以了。
上面这个就是Spring Cloud Alibaba代码兼容问题。
在进行整合前也对官方文档进行了查阅,在官方明确表示支持的情况下进行了下一步的实操,最后发现还是有一些坑。好在坑比较好填,不然就得去降级Nacos了,重新装又是麻烦事。