前言
本文素材起源敌人学习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
一开始敌人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; } }
浏览器通过nginx拜访没问题,然而我的项目中把nacos服务地址配置为nginx ip就报了
com.alibaba.nacos.api.exception.NacosException: Client not connected, current status:STARTING
这个异样信息,前面敌人查资料,官网上有写
于是他就将转发形式改为TCP,他的nginx版本是1.9+以上版本,默认就反对TCP代理了,不必额定装置stream模块。nginx配置TCP的示例形如下
stream { upstream nacos-cluster-grpc{ # nacos2版本,grpc端口与要比主端口多1000,主端口为7777、8888、9999 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; }}
当敌人配置好nginx tcp代理转发后,通过telnet命令
telnet 127.0.0.1 9848
来看是否能失常转发给nacos服务端,通过验证,网络能够连通。接着敌人在微服务项目的nacos配置填写如下地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:9848 #nginx代理tcp的地址
原本认为高枕无忧,后果我的项目一启动,依然报
com.alibaba.nacos.api.exception.NacosException: Client not connected, current status:STARTING
于是敌人懵了,啥状况?就来找我交换一下
其实在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、首先解析主端口号的外围代码
地位在
com.alibaba.nacos.common.remote.client.RpcClient#resolveServerInfo
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)); }
2、其次设置grpc端口的外围代码
地位在:
com.alibaba.nacos.common.remote.client.grpc.GrpcClient#connectToServer
端口设置就是在截图圈红局部,而后从this.rpcPortOffset()咱们能够发现
public int rpcPortOffset() { return Integer.parseInt(System.getProperty("nacos.server.grpc.port.offset", String.valueOf(Constants.SDK_GRPC_PORT_DEFAULT_OFFSET))); }
这个偏移量是能够通过nacos.server.grpc.port.offset进行批改,不批改默认就是1000。因而跟踪源码,咱们能够得出另外一种解法。在微服务的nacos配置依然填代理的nginx 的tcp地址,示例
spring.cloud.nacos.discovery.server-addr=127.0.0.1:9848 #nginx代理tcp的地址
同时启动的时候,加上
-Dnacos.server.grpc.port.offset=0
或者在主启动类硬编码也 能够
System.setProperty("nacos.server.grpc.port.offset","0");
注: 这边很重要的细节点就是: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