没错,使用 Nacos 踩坑了

沙海 2021年6月10日02:44:20Java评论33字数 3085阅读10分17秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/30742.html

服务都下线了,日志里面也是一堆报错,我下意识以为线上炸了,赶紧上线排查。这个报错我第一次见,看异常堆栈,字面意思便是域名解析出问题了。NacosException,从而导致心跳线程没有catch住异常,彻底停止发送心跳了!这也就成功解释了,为什么短暂的域名解析失败,会导致服务全部下线了。该问题仅存在于1.4.1版本,低于此版本不受此问题的影响,使用1.4.1的用户建议升级至1.4.2以避免此问题。文章源自JAVA秀-https://www.javaxiu.com/30742.html

原文约 3859 | 图片 14 | 建议阅读 8 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了

芋道源码 文章源自JAVA秀-https://www.javaxiu.com/30742.html

以下文章来源于Kirito的技术分享,作者kiritomoe文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

Kirito的技术分享文章源自JAVA秀-https://www.javaxiu.com/30742.html

「技术分享」某种程度上,是让作者和读者,不那么孤独的东西。「Kirito的技术分享」致力于探讨 Java 生态的知识点,内容覆盖分布式服务治理,微服务,性能调优,各类源码分析。追求有深度并兼具表达力的文字。文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

点击上方“芋道源码”,选择“设为星标文章源自JAVA秀-https://www.javaxiu.com/30742.html

管她前浪,还是后浪?文章源自JAVA秀-https://www.javaxiu.com/30742.html

能浪的浪,才是好浪!文章源自JAVA秀-https://www.javaxiu.com/30742.html

每天 8:55 更新文章,每天掉亿点点头发...文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

源码精品专栏文章源自JAVA秀-https://www.javaxiu.com/30742.html

 文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

问题发现

就在这周,我接到 MSE Nacos 用户的反馈,说线上 Nacos 不可用,服务都下线了,日志里面也是一堆报错,我下意识以为线上炸了,赶紧上线排查。本文主要记录这次问题的排查过程,以及解决方案。文章源自JAVA秀-https://www.javaxiu.com/30742.html

首先看用户反馈的报错,日志如下:文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

并且用户反馈业务日志也出现了大量的服务地址找不到的报错,说明 Nacos 服务都下线了。文章源自JAVA秀-https://www.javaxiu.com/30742.html

我立刻查看了服务端的监控,发现用户的 MSE Nacos 集群并无异常,cpu/内存等指标有下降,并没有异常行为,排除了服务端异常的可能性。文章源自JAVA秀-https://www.javaxiu.com/30742.html

随即将视线聚焦在了客户端。老实说,这个报错我第一次见,看异常堆栈,字面意思便是域名解析出问题了。这个报错大概持续了 10 分钟,立刻让用户在业务节点上使用 ping、dig 等工具确认域名解析是否正常,测试发现均无异常。继续让用户 telnet mse-xx.com 8848,发现也能够 telnet 通。文章源自JAVA秀-https://www.javaxiu.com/30742.html

根据这些现象,大概能得出结论:用户的机器上出现了短暂的域名解析问题,导致短时间访问不通 MSE Nacos。但用户继续反馈说,一部分重启以后的机器已经恢复了,但没有重启的机器,竟然还会出现调用报错。不然怎么说重启大法好呢,但也加深了问题的诡异性。文章源自JAVA秀-https://www.javaxiu.com/30742.html

正当一筹莫展时,另一用户也找上来了,竟然也是一样的问题,并且由于第二个用户还同时使用了 redis,报错日志中除了出现 nacos 的域名解析问题,还报了 redis 的域名解析报错。至此,更加坚定了我之前推测,根因肯定是域名解析出现了故障,导致这两个用户收到了影响。但问题在于,为什么短暂的域名解析失败(大概 10 分钟),会导致持续性的 Nacos 问题呢?并且只有重启才能恢复。文章源自JAVA秀-https://www.javaxiu.com/30742.html

分析两个用户的共性,最终我和同事将可疑点锁定在了 Nacos 客户端版本上,对比发现,用户都是同一个报错,并且竟然都是 nacos-client 1.4.1 版本。文章源自JAVA秀-https://www.javaxiu.com/30742.html

Nacos 1.4.1 版本引入的 bug

在问题发生时,Nacos 1.x 最新的版本已经是 Nacos 1.4.2 了,将源码 checkout 到 1.4.1 版本,追踪堆栈附近的问题,文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

上述这段代码是 Nacos 访问服务端的一段代码,进入 595 行,一探究竟。文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

我们成功找到了堆栈中的直接报错,就是这段 IsIPv4 的判断触发。splitIPPortStr 这个方法的主要逻辑是从 Nacos 的连接串筛选出连接地址,主要是为了做默认端口号的判断,如果用户没有携带 8848,会默认带上 8848。文章源自JAVA秀-https://www.javaxiu.com/30742.html

但问题恰恰便是出现在这儿:文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

InetAddress.getByName(addr) 是一个内置的方法,描述如下:文章源自JAVA秀-https://www.javaxiu.com/30742.html

Given the name of a host, returns an array of its IP addresses, based on the configured name service on the system.

意思是把一个域名传给操作系统,返回一串 IP,这不就是域名解析吗!我当时就很好奇,你说你判断 IPv4 格式,为啥要这么判断呢?直接判断 IPv4 的 pattern 不行吗?而这段代码,恰恰是导致问题的凶手之一。文章源自JAVA秀-https://www.javaxiu.com/30742.html

我们看看 1.4.2,已经修复了这个逻辑了,直接改成了正则判断。文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

但疑问还是存在的,域名解析短暂失败了,为啥会导致服务全都下线了,并且解析恢复后,服务依旧没有上线呢?文章源自JAVA秀-https://www.javaxiu.com/30742.html

继续追踪这段代码,发现 callServer 这段代码会被 com.alibaba.nacos.client.naming.beat.BeatReactor 持有,用于维持自身和 Nacos 的心跳。文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

而由于上述域名解析失败,抛出的异常是 IllegalArgumentException,并没有被里层方法转换成 NacosException,从而导致心跳线程没有 catch 住异常,彻底停止发送心跳了!文章源自JAVA秀-https://www.javaxiu.com/30742.html

这也就成功解释了,为什么短暂的域名解析失败,会导致服务全部下线了。(Nacos 是利用心跳维护和 server 端的存活状态的)文章源自JAVA秀-https://www.javaxiu.com/30742.html

改进建议

  1. 修改 isIPv6 和 isIPv4 的判断方式,改为正则匹配。上文提及,这点已经在 1.4.2 修复了。文章源自JAVA秀-https://www.javaxiu.com/30742.html

  2. 心跳线程要保证不被异常中断下一次心跳的提交。文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

图片文章源自JAVA秀-https://www.javaxiu.com/30742.html

第二点,也已经被修复了。文章源自JAVA秀-https://www.javaxiu.com/30742.html

总结

nacos-client 1.4.1 存在严重的 bug,客户端与 Nacos Server 如果发生短暂的域名解析问题,会导致心跳永久丢失,进而引发服务全量下线,即使网络恢复,也不会自动恢复心跳。文章源自JAVA秀-https://www.javaxiu.com/30742.html

域名解析失败常见于网络抖动或者 K8s 环境下的 coreDNS 访问超时等场景,为避免域名解析对 Nacos 造成的重大影响,请务必自查应用代码中使用的 nacos-client 的版本。文章源自JAVA秀-https://www.javaxiu.com/30742.html

该问题仅存在于 1.4.1 版本,低于此版本不受此问题的影响,使用 1.4.1 的用户建议升级至 1.4.2 以避免此问题。文章源自JAVA秀-https://www.javaxiu.com/30742.html

使用 SpringCloud/Dubbo 的用户,需要确认实际框架使用的 nacos-client 版本,可以通过显式指定 nacos-client 的版本以覆盖框架默认的版本。其中 Dubbo 用户要格外小心,Dubbo 的 2.7.11 版本默认使用了 nacos-client 1.4.1,务必显式指定 nacos-client 的版本到 1.4.2,Dubbo 也将在下个 release 版本替换 Nacos 的默认版本。文章源自JAVA秀-https://www.javaxiu.com/30742.html

- END -文章源自JAVA秀-https://www.javaxiu.com/30742.html

欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

已在知识星球更新源码解析如下:文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

没错,使用 Nacos 踩坑了文章源自JAVA秀-https://www.javaxiu.com/30742.html

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。文章源自JAVA秀-https://www.javaxiu.com/30742.html

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。文章源自JAVA秀-https://www.javaxiu.com/30742.html

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章源自JAVA秀-https://www.javaxiu.com/30742.html

文章有帮助的话,在看,转发吧。谢谢支持哟 (*^__^*)
文章源自JAVA秀-https://www.javaxiu.com/30742.html

阅读原文文章源自JAVA秀-https://www.javaxiu.com/30742.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
  • 版权声明:本站是JAVA秀团队的技术分享社区,我们会经常分享资源和教程。
  • 转载请注明:没错,使用 Nacos 踩坑了 - JAVA秀 ☜(ˆ▽ˆ)
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定