• 记一次使用nacos2踩到的坑


    前言

    本文素材来源朋友学习nacos2.1.1踩到的坑。直接上正菜

    坑点一:出现端口被占用

    因为是学习使用,朋友就在物理机搭建了搭建了nacos伪集群,即ip都一样,端口分别为8848,8847,8849。然而启动nacos服务器后,一台正常启动,其他两台都报了端口被占用

    出现这种情况的原因,官网有做了解释


    通过官网我们可以很容易得知,这个端口被占用主要是因为grpc引起的,因为他端口的生成方式,是由主端口+1000、主端口+1001生成。

    解决方法

    集群的端口不要采用相邻数字,步长尽量搞大点。比如设置为7777、8888、9999之类的

    坑二:微服务项目启动出现com.alibaba.nacos.api.exception.NacosException: Client not connected, current status:STARTING异常

    这个问题出现在朋友在项目中配置的nacos地址为nginx地址,配置示例如下

    spring.cloud.nacos.discovery.server-addr=nginx ip
    
    • 1

    一开始朋友nginx的配置示例如下

    upstream nacos-cluster { 
    		server 127.0.0.1:7777;
    		server 127.0.0.1:8888;
    		server 127.0.0.1:9999;
       }
        server {
            listen       80;
            server_name  localhost;
            location / {
                proxy_pass http://nacos-cluster;
            }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    浏览器通过nginx访问没问题,但是项目中把nacos服务地址配置为nginx ip就报了

    com.alibaba.nacos.api.exception.NacosException: Client not connected, current status:STARTING
    
    • 1

    这个异常信息,后面朋友查资料,官网上有写


    于是他就将转发方式改为TCP,他的nginx版本是1.9+以上版本,默认就支持TCP代理了,不用额外安装stream模块。nginx配置TCP的示例形如下

    
    stream {
    	upstream nacos-cluster-grpc{
    	    # nacos2版本,grpc端口与要比主端口多1000,主端口为777788889999
    	    server 127.0.0.1:8777;
    		server 127.0.0.1:9888;
    		server 127.0.0.1:10999; 
    	}
    	server{
    	   listen 9848;
            proxy_pass nacos-cluster-grpc;
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    当朋友配置好nginx tcp代理转发后,通过telnet命令

    telnet 127.0.0.1 9848
    
    • 1

    来看是否能正常转发给nacos服务端,经过验证,网络可以连通。接着朋友在微服务项目的nacos配置填写如下地址

    spring.cloud.nacos.discovery.server-addr=127.0.0.1:9848 #nginx代理tcp的地址
    
    • 1

    本来以为万事大吉,结果项目一启动,仍然报

    com.alibaba.nacos.api.exception.NacosException: Client not connected, current status:STARTING
    
    • 1

    于是朋友懵了,啥情况?就来找我交流一下

    其实在nacos官网的FAQ就有提到相应的解题思路了


    因为我们在nginx配置的代理tcp端口为9848,这个端口可以看成是grpc的端口,因为grpc的端口 = nacos主端口 + 1000,因此我们套这个公式就可以得出,nacos的主端口为 = 9848 - 1000 = 8848,而我们微服务项目配置nacos端口,其实配置是主端口,因此实际上我们配置要写成

    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 #nginx代理tcp端口 - 1000
    
    • 1

    配置这个后,果然成功注册。这个思路是官网带给我们的,但作为一个有点追求的程序员应该不会仅仅满足与此,我们可以直接根据控制台报出的异常来获取答案

    异常排查过程就省略了,直接贴出关键的解题代码

    1、首先解析主端口号的核心代码

    位置在

    com.alibaba.nacos.common.remote.client.RpcClient#resolveServerInfo
    
    • 1
    ServerInfo private RpcClient.ServerInfo resolveServerInfo(String serverAddress) {
            Matcher matcher = EXCLUDE_PROTOCOL_PATTERN.matcher(serverAddress);
            if (matcher.find()) {
                serverAddress = matcher.group(1);
            }
    
            String[] ipPortTuple = serverAddress.split(":", 2);
            int defaultPort = Integer.parseInt(System.getProperty("nacos.server.port", "8848"));
            String serverPort = (String)CollectionUtils.getOrDefault(ipPortTuple, 1, Integer.toString(defaultPort));
            return new RpcClient.ServerInfo(ipPortTuple[0], NumberUtils.toInt(serverPort, defaultPort));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2、其次设置grpc端口的核心代码

    位置在:

    com.alibaba.nacos.common.remote.client.grpc.GrpcClient#connectToServer
    
    • 1


    端口设置就是在截图圈红部分,然后从this.rpcPortOffset()我们可以发现

    public int rpcPortOffset() {
            return Integer.parseInt(System.getProperty("nacos.server.grpc.port.offset", String.valueOf(Constants.SDK_GRPC_PORT_DEFAULT_OFFSET)));
        }
    
    • 1
    • 2
    • 3

    这个偏移量是可以通过nacos.server.grpc.port.offset进行修改,不修改默认就是1000。因此跟踪源码,我们可以得出另外一种解法。在微服务的nacos配置仍然填代理的nginx 的tcp地址,示例

    spring.cloud.nacos.discovery.server-addr=127.0.0.1:9848 #nginx代理tcp的地址
    
    • 1

    同时启动的时候,加上

    -Dnacos.server.grpc.port.offset=0
    
    • 1

    或者在主启动类硬编码也 可以

        System.setProperty("nacos.server.grpc.port.offset","0");
    
    • 1

    注: 这边很重要的细节点就是:GRPC port = 主端口 + grpc端口偏移量,这个计算出来的端口值要和nginx代理tcp 端口值相等。

    总结

    因为朋友用的是目前最新版的nacos2,所以有些问题搜索引擎不是那么好找答案,因此遇到这种问题,最好的解题思路就是官网和相应的github,还有就是源码跟踪了。

    后面那个
    Client not connected, current status:STARTING,其实还有一种解法,就是把客户端版本调低到1.x版本,因为这个问题本质上是连接不上grpc问题,因此我们可以不用grpc,直接用http就好了,而2.x服务端版本是同时支持http和grpc,因此客户端版本调成1.x,他就是以http的方式和服务端进行交互。不过是不建议这么做,因为你升级了2.x,有一方面就是为高性能,如果把版本降低,那还不如直接使用1.x就好了。

    还有文中的那两种解法,我个人是建议不要改偏移量,直接通过主端口 + 1000这种方式去算就好了

    附录

    本文很多关于nacos2解题思路都是出自官网这篇文章

    https://nacos.io/zh-cn/docs/2.0.0-compatibility.html

  • 相关阅读:
    7-8 HashSet存入自定义类对象
    Linux-进程管理
    1600*C. Game On Leaves(博弈游戏&树)
    SCUI Admin - 基于 Vue3 和 Element Plus 开发的 admin 前端 UI 框架,不仅免费开源,还有很多现成的业务组件、页面模板
    内外“双驱”, NFT价值UPUP
    3.4 bp,si,di寄存器,寻址方式,寄存器总结
    Harbor企业级私服Docker镜像仓库搭建及应用
    copy archived log from ASM 异地恢复归档
    LeetCode 232.用栈实现队列
    牛顿迭代法求平方根--C++简单实现
  • 原文地址:https://blog.csdn.net/kingwinstar/article/details/126409445