ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Nacos 2.x 9848端口连接失败排查:从gRPC到安全组全解析

Nacos 2.x 9848端口连接失败排查:从gRPC到安全组全解析 写这个排查帖之前,先说个现象:应用日志里明明显示Nacos注册成功,8848端口telnet也通,但过一会儿就报错,客户端一直提示“Connection refused /ip:9848”。遇到过好几回,基本每次都在运维或者云控制台的安全组里找到原因。这篇文章就把这类问题的排查思路、底层原理和实操命令完整捋一遍,给正在被9848端口折磨的Java开发一个可以直接抄作业的清单。1. 为什么Nacos 2.x要额外开一个9848端口1.1 8848和9848的关系,不止是1000的差值Nacos 2.x没出来之前,8848就是唯一的入口。客户端通过HTTP请求做注册、查询、订阅,服务端有变更就靠客户端轮询拉取,实时性和效率都有点勉强。Nacos 2.0开始引入gRPC通信框架,客户端和服务端之间建立长连接,服务端可以主动把配置变更、服务上下线消息推给客户端,不用再频繁轮询。这里就出现了一个非常容易让新手懵的端口设计:主端口依然保持8848,但gRPC通信端口不是额外再配一个独立端口,而是按照“主端口1000”自动偏移。所以:8848:HTTP为主的老端口,也是整个Nacos的对外主端口9848:客户端gRPC端口,等于884810009849:服务端之间通信的gRPC端口,等于88481001很多人习惯只检查8848是否放通,觉得“注册都成功了,端口肯定没问题”,实际上客户端建立gRPC长连接使用的是9848。只要9848被防火墙、安全组或者容器端口映射挡住,客户端依然能通过8848完成部分HTTP操作,但长连接建立不起来,后续的服务健康检查、配置推送、订阅通知都会出问题。1.2 客户端为什么一定要连gRPC端口Nacos客户端在启动时会先通过8848拿到服务端信息,然后立刻向gRPC端口发起长连接。这个连接一旦建立,客户端后续的注册心跳、配置监听、服务订阅全部走这条通道。9848连不上,最常见的表现是:服务能注册到Nacos控制台,但过一会儿就被标记为不健康配置中心可以拉到一次配置,但后续动态刷新不生效日志里反复出现类似“Client not connected, current status:STARTING”或者“Fail to connect to server”的信息我见过有人为了绕过9848,试图在客户端配置里把gRPC端口关掉,或者把通信方式改回HTTP。Nacos官方并没有提供这样的开关,或者说这种操作只存在于很老的测试版本里。正确做法就是老老实实把9848端口放通,同时了解清楚为什么Nacos要改成这种架构——长连接方案在注册中心和配置中心这种场景下,推送实时性和服务端负载表现确实比HTTP轮询好太多。2. 先别改代码,按这个顺序确认端口状态2.1 服务端是否真的监听了9848排查这种问题,第一步永远是确认服务端有没有把9848端口监听起来。如果Nacos服务端根本没起来,或者起来了但监听在错误的地址上,客户端跑到天亮也连不上。在Nacos服务器上执行:ss -lntp | grep 9848或者用更传统一点的命令:netstat -tlnp | grep 9848正常输出类似:LISTEN 0 128 *:9848 *:* users:((java,pid21173,fd135))看到java进程监听在0.0.0.0:9848,说明端口本身是起来的。如果没有任何输出,就要检查Nacos服务端是不是2.x版本,因为1.x版本根本没有9848端口。再看Nacos进程是不是还在跑,有时候系统OOM把进程杀掉,8848端口也没了,这时候就不会是“8848通9848不通”的问题,而是全部不通。还有一点容易被忽略:如果Nacos是Docker容器方式部署,宿主机上执行ss -lntp看到的监听端口未必等于容器内端口。正确做法是先进入容器看监听状态,再检查容器端口映射:docker ps | grep nacos输出里需要看到类似0.0.0.0:8848-8848/tcp, 0.0.0.0:9848-9848/tcp这样的映射。很多业务方会把8848映射出来,却忘了加9848,从宿主机看8848正常,但9848请求根本进不了容器。2.2 用telnet和nc做连通性测试服务端端口确认在监听之后,接下来要在应用所在的机器上做连通性测试。这一步的目的很纯粹:把“应用配置问题”和“网络不通问题”区分开。最简单的命令:telnet 192.168.1.100 9848如果端口通,会显示Connected to 192.168.1.100。如果卡住不动或者提示Connection refused,说明TCP层都建立不了连接。在没有telnet的容器镜像或者精简系统里,可以用nc:nc -vz 192.168.1.100 9848返回Connection to 192.168.1.100 9848 port [tcp/*] succeeded!就表示通。需要强调一个细节:telnet通不代表应用能正常使用gRPC协议。9848端口上跑的是gRPC,不是纯HTTP。有些场景下TCP端口通,但Nacos服务端返回的协议握手不对,这通常是版本兼容问题,后面单独说。反过来,TCP不通就一定用不了gRPC,先解决网络问题。2.3 别忽略docker映射和控制台显示还有一个高频场景:开发和本地联调的时候,Nacos跑在Docker里,端口映射只写了8848。从浏览器打开控制台完全正常,注册也看起来正常,但应用日志里正在疯狂重试连接9848。这种问题在测试环境特别容易出现,因为开发机本地端口往往没限制,而测试服务器上有防火墙,大家习惯性只关注8848。如果你用的是docker-compose,记得Nacos容器要同时映射这三个端口:ports: - 8848:8848 - 9848:9848 - 9849:98499849在单机模式不是必须,但集群环境建议一起放出来。后面有一节专门讲9849,这里先记住一句话:端口映射是端口列表,不是只映射“看起来在用的那个”。3. 防火墙与云安全组:最常见的背锅侠3.1 云服务器安全组怎么放行如果服务端端口监听正常,应用所在机器telnet又不通,那十有八九是防火墙级别拦了。云服务器上第一嫌疑就是安全组。不管是阿里云、腾讯云还是华为云,安全组规则都要同时考虑入方向和出方向。对于Nacos这种场景,客户端访问服务端,重点看服务端所在云主机的入方向规则。控制台操作路径一般是:实例详情-安全组-配置规则-入方向-手动添加。需要添加的规则:授权对象:客户端所在网段,一般填应用服务器的内网IP或者整个VPC网段协议端口:TCP 8848授权对象:同上协议端口:TCP 9848很多人会把8848配成0.0.0.0/0全放行,到了9848反而只填了一个未生效的旧IP段。建议把需要访问Nacos的所有来源网段都整理一遍,8848和9848同步放行,免得8848能通9848不能通。另外注意,有些云平台安全组默认只对TCP 8848这种单端口生效,一次只能加一条规则,不会自动连带“1000端口”。这就是为什么安全组里8848开放了,9848还是别人口中“玄学不通”的真实原因——不是玄学,是没配。3.2 Linux防火墙操作实例不是云主机或者没走安全组的情况下,Linux本机防火墙是另一个拦截点。以CentOS 7/8常见的firewalld为例:firewall-cmd --permanent --add-port9848/tcp firewall-cmd --reload firewall-cmd --list-ports看到输出里包含9848/tcp就算生效。如果你用的是iptables:iptables -I INPUT -p tcp --dport 9848 -j ACCEPT service iptables save需要注意,iptables规则的顺序很重要,如果前面有一条DROP ALL规则,新插入的ACCEPT规则必须放在更靠前的位置。用-I INPUT插到最前面一般都能生效,用-A INPUT追加到最后面可能被DROP规则拦掉。还有一种情况是云主机默认启用了firewalld,而且Nacos是部署在宿主机上的,但应用在另一个内网段。这时候除了放行端口,还要确认没有额外的网段拦截规则。可以用:firewall-cmd --list-all查看当前活动的区域和规则列表,重点看source和services部分。3.3 云原生环境里的额外检查点现在越来越多团队把Nacos部署在Kubernetes或者容器环境里,排查逻辑要再上一层。K8s里常见的坑是Service只暴露了8848端口,Pod本身的9848端口没写进Service的targetPort。检查Nacos Service:kubectl get svc nacos -o yaml重点看ports部分,一个完整配置应该是这样:ports: - name: http port: 8848 targetPort: 8848 - name: grpc port: 9848 targetPort: 9848如果Service只暴露了8848,应用通过Service域名访问Nacos,HTTP请求可以转发到Pod,但gRPC请求到达Service时根本没有对应的9848端口,自然会连接失败。Ingress也是同理,Nacos的gRPC通信一般不适合走HTTP域名,除非单独做了TCP四层转发。我个人建议云原生环境里,应用访问Nacos直接走ClusterIP或者Headless Service,少绕一层,少一个坑。4. 客户端版本与配置引发的连接异常4.1 客户端版本与服务端版本匹配9848连不上,除了网络问题,版本兼容性是第二大类原因。Nacos 1.x服务端没有gRPC端口,如果客户端是2.x版本,启动时会尝试连接9848,失败后表现就是注册不了或者一直重试。反过来,Nacos 2.x服务端为了兼容老客户端,默认保留了HTTP接口,1.x客户端勉强能注册,但用不了新特性。这两种情况都容易让人误判成“端口问题”。建议统一把客户端和服务端都升级到2.x大版本内的相近小版本。比如服务端用2.2.3,Spring Cloud Alibaba这边对应的Nacos client版本也应保持一致或小版本更高。我用Spring Boot项目时的经验是,先查spring-cloud-alibaba-dependencies对应的版本号,再去Maven仓库确认它里面引的nacos-client版本,避免依赖冲突。具体到Spring Cloud项目,查看当前nacos-client版本:mvn dependency:tree -Dincludescom.alibaba.nacos:nacos-client输出里如果有多个nacos-client版本,容易出幺蛾子。多个版本共存时,高版本和低版本的gRPC协议可能有差异,导致连接失败或推送异常。这时候就要排除旧版本依赖,统一为一个版本。4.2 server-addr配置和自动端口偏移Nacos客户端连接gRPC端口,并不需要你在配置里额外写9848这个数字。客户端通过server-addr拿到主端口后,自动加1000得到gRPC端口。所以配置还是:spring: cloud: nacos: discovery: server-addr: 192.168.1.100:8848 config: server-addr: 192.168.1.100:8848不要画蛇添足去改什么grpcPort,也不要手动写192.168.1.100:9848作为server-addr。即使你写了9848,客户端反而会把它当成主端口,再算一次偏移,效果大概率更乱。还有一个容易忽略的坑:如果服务端设置了偏移量或者自定义了gRPC端口,客户端自动“1000”就不准确。比如服务端主端口改成了9900,那么gRPC端口默认是10900。如果你在安全组里只放了9900,没放10900,客户端连gRPC照样失败。排查的时候不要只认“9848”这个数字,要先搞清楚服务端实际用的是哪几个端口。4.3 版本不匹配时如何快速定位判断是不是版本问题,最直接的办法是看客户端日志。Nacos客户端会把连接失败的原因打印出来,常见两种:Connection refused: /192.168.1.100:9848:TCP层面被拒绝,优先查防火墙、安全组、端口映射grpc call failed或者Timed out after 3000 milliseconds:端口可能通了,但协议握手不成功,大概率是版本不匹配我在实际排查时有一个习惯:直接把客户端日志级别调成DEBUG再启动一次。Spring Boot项目里:logging: level: com.alibaba.nacos: debug日志会详细打出当前使用的Nacos版本、连接的IP和端口、重试逻辑。看到类似Try to connect to server 192.168.1.100:9848就知道客户端确实在连9848,再看失败原因就能区分是网络问题还是协议问题。如果服务端是裸Nacos进程,还可以看服务端日志logs/nacos.log,搜关键字“gRPC”或“9848”,确认服务端有没有收到来自客户端IP的连接请求。服务端日志完全没有对应请求,那说明请求根本没到服务端,继续查网络链路。5. 一次完整的“8848通、9848不通”排查复盘5.1 现场现象与日志证据分享一个我处理过的典型案例。当时是一个Spring Boot应用要接入Nacos注册中心和配置中心,报错信息如下:应用启动时部分成功,能读取配置,也能注册服务稍后日志出现:[NA] [gRPC] Fail to connect to server 10.0.0.5:9848Nacos控制台能看到服务实例,但状态一会儿健康一会儿不健康团队成员telnet了8848,显示通,于是都怀疑是Nacos服务端有问题这类现象最大的迷惑点在于“8848通”让人放松警惕。实际上Nacos 2.x客户端有两个阶段:先通过8848完成基础交互,再建立9848长连接。长连接建立不起来,注册信息可能能上报,但后续健康检查会失败。我还特意看了一下客户端完整堆栈,发现报错来源不是HTTP接口,而是GrpcClient连接。这就直接锁定了问题是在gRPC通道上。5.2 排查步骤与关键输出我按下面的顺序一步步处理:第一步,远程登录Nacos服务端,查看端口:ss -lntp | grep -E 8848|9848|9849输出显示8848、9848、9849都在监听,而且PID都是同一个Java进程。这说明服务端本身没毛病。第二步,从应用所在机器telnet Nacos服务端9848端口:telnet 10.0.0.5 9848结果卡住,一段时间后提示Connection timed out。同一个机器telnet 8848秒通。到这里,问题已经确认在网络层,不是应用配置问题。第三步,检查云服务器安全组。控制台上Nacos主机入方向规则里只有TCP 8848放行,没有9848。添加了一条TCP 9848放行规则,来源设为应用所在网段10.0.1.0/24。第四步,重新telnet:telnet 10.0.0.5 9848这次秒通,显示Connected to 10.0.0.5。第五步,重启应用。这次日志不再报gRPC连接失败,Nacos控制台实例状态也稳定为健康。整个过程耗时不到十分钟,但前面团队已经卡了两天,主要是一开始就默认“8848能连说明网络没问题”,忽略了两套通信机制并存的事实。5.3 最终处理方案与验证端口放行之后我再强调一个主动验证方式,不要等应用自己报错。可以先在应用机器上循环ping一下端口,确认重连成功:nc -vz 10.0.0.5 9848在Nacos控制台里观察服务所在集群,实例的“健康实例数”稳定、不会忽上忽下。配置中心那边也试一次动态修改配置:改一个配置项,应用日志里当前时间就能收到变更推送。这一步能顺带验证gRPC长连接的数据通道是否正常,因为光有TCP连通不代表推送链路一定没问题。我个人的习惯是,这类端口放行操作完了之后,再顺手把防火墙规则导出存到运维文档里,避免下次扩机器或者换环境的时候再踩一遍同样的坑。6. 关于9848端口,你还需要知道的几个细节6.1 端口偏移规则与自定义端口Nacos主端口如果做了调整,9848、9849会跟着自动偏移,偏移公式是主端口1000、主端口1001。比如主端口设置成9000,那么客户端gRPC端口是10000,服务端gRPC端口是10001。这里有一个容易忽略的点:如果你在Nacos服务端配置文件里自定义了主端口,却没跟着调整防火墙规则,客户端会按照新主端口计算偏移。很多线上故障就是这么产生的——改配置的时候只记着改8848,忘了把对应偏移端口也加到安全组。另外,只要自定义端口不与其他进程冲突,一般没问题;如果9848被其他程序占了,客户端gRPC连接会直接失败,而且8848看起来依然正常。在较新版本中,Nacos官方也支持直接配置grpc相关端口,具体参数名在不同版本略有差异。如果你真的需要自定义,建议先确认当前Nacos版本对应的官方文档,不要照搬网上的老参数。优先让偏移逻辑自动生效,这是最稳妥的方案。6.2 9849端口要不要一起放行9849是服务端与服务端之间的gRPC通信端口,和客户端关系不大。如果你部署的是Nacos单机模式,只做开发和测试,那么只需要放行8848和9848。如果是集群模式,三个端口都要放行,否则节点之间无法正常同步,会出现注册数据不一致、选举异常等问题。判断集群是否正常,有一个很直观的检查方式:登录Nacos控制台,在“集群管理”页面看每个节点状态。如果节点列表里的IP能正常显示,端口状态都正常,9849大概率没问题。如果某个节点显示异常,先检查该节点上9849端口是否监听,以及集群内安全组是否互相放行了9849。还有一个容易被绕进去的点:有时候服务端之间用内网通信,客户端的健康检查却需要走另一个网段。这种场景下,千万别抱着“9848放行了,9849自然也放行了”的想法,安全组规则是独立的,必须逐条确认。6.3 经验总结:连接问题的排查顺序遇到“应用能启动但Nacos连接异常”,我建议按以下顺序排查,基本不走弯路:看客户端日志,确定具体报错端口是8848还是9848在Nacos服务端确认8848、9848、9849是否都正常监听从应用所在机器分别telnet这三个端口,记录连通结果TCP不通,按“服务端防火墙 - 云安全组 - 容器端口映射 - 云原生Service配置”逐层排查TCP都通但还是报错,检查客户端和服务端版本兼容性以及依赖版本冲突使用DEBUG日志确认客户端实际连接的端口和IP,防止被配置代理或中间层干扰这套顺序我用了很多次,每次都能很快缩小范围。最怕的是跳过前面几步,直接去翻代码找配置,最后发现根本改错地方。最后说一句个人的真实感受:排查这类问题,最大的障碍不是技术难度,而是第一印象太过迷惑。“8848能通”会让所有人下意识觉得Nacos没问题,但Nacos 2.x早就不是单端口应用了。以后只要看到Nacos连接相关报错,先把8848、9848、9849三个端口一起检查一遍,十次里能省下九次折腾的时间。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进