老旧Spring Cloud 2.0.0.RELEASE使用最新版本Nacos 2.2.3

前言

本文主要将使用旧版本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客户端版本就可以使用。
文档地址

通过官方文档的这两段描述明确了两点:

  • 老版本Nacos客户端是可以被新版本Nacos服务端兼容的。
  • 老版本Spring Cloud也是可以兼容新客户端版本的。

实践中遇到的坑

初一看在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了,重新装又是麻烦事。

你可能感兴趣的:(spring,cloud,spring,后端)