What?一个 Dubbo 服务启动要两个小时!
前言
前几天在测试环境碰到一个非常奇怪的与 dubbo 相关的问题,事后我在网上搜索了一圈并没有发现类似的帖子或文章,于是便有了这篇。
希望对还未碰到或正在碰到的朋友有所帮助。
现象
现象是这样的,有一天测试在测试环境重新部署一个 dubbo 应用的时候发现应用“启动不起来”。
但过几个小时候之后又能自己慢慢恢复,并能够对外提供 dubbo 服务。
但其实经过我后续排查发现刚开始其实并不是启动不起来,而是启动速度非常缓慢,所以当应用长时间启动后才会对外提供服务。
而这个速度慢到居然要花费 2 个小时。
导致的一个结果是测试完全不敢在测试环境发版验证了,每验证一个功能修复一个 bug 就得等上两个小时,这谁受得了😂。
而且经过多次观察,确实每次都是花费两小时左右应用才能启动起来。
尝试解决
最后测试顶不住了,只能让我这个“事故报告撰写专家”来看看。
当我得知这个问题的现象时其实完全没当一回事:
都不用想,这不就是主线程阻塞了嘛,先看看是否在初始化的时候数据库、Zookeeper 之类的连不上导致阻塞了-------来之多次事故处理的经验告诉我。
于是我把这事打回给测试让他先找运维排查下,不到万不得已不要影响我 Touch fish🐳。
第二天一早看到测试同学的微信头像跳动时我都已经准备接受又一句 “膜拜大佬👍” 的回复时,却收到 “网络一切正常,没人动过,再不解决就要罢工了🤬”。
好吧,忽悠不过去了。
首先这类问题的排查方向应该不会错,就是主线程阻塞了,至于是啥导致的阻塞就不能像之前那样瞎猜了。
我将应用重启后用 jstack pid 将线程快照打印到终端,直接拉到最后看看 main 线程到底在干啥。
前几次的快照都是很正常:
加载 Spring ---->连接 Zookeeper ---> 连接 Redis,都是依次执行下来没有阻塞。
隔了一段后应用确实还没起来,我再次 jstack 后得到如下信息:
翻源码
我一直等了十几分钟再多次 jstack 得到的快照得到的信息都是一样的。
如图所示可见主线程是卡在了 dubbo 的某个方法 ServiceConfig.java 的 303 行中。
于是我找到此处的源码:
简单来说这里的逻辑就是要获取本机的 IP 将其注册到 Zookeeper 中用于其他服务调用。
再往下跟就如堆栈中一样是卡在了 Inet4AddressImpl.getLocalHostName 处。
但这是一个 native 方法,我们应用也根本干涉不了,最终的现象就是调用这个本地方法非常耗时。
于是这问题貌似也阻塞在这儿了,没有太多办法。
最终解决
既然这是一个 native 方法,那说明和应用本身没有啥关系(确实也是这样,这个问题是突然间出现的。)
那是否是服务器本身的问题呢,想到在 native 方法里是获取本机的 hostname,那是否和这个 hostname 有关系呢。
这是在我自己的阿里云服务器上测试,真正的测试环境不是这个名字。
拿到服务器 hostname 后再尝试 ping 这个 hostname,奇怪的现象发生了:
命令刚开始会卡住一段时间(大概几十秒),然后才会输出 hostname 对应的 ip 以及对应的延迟。
而当我直接 ping 这个 ip 时却能快速响应后面的输出。
最后我尝试在 /etc/hosts 配置文件中加入了对应的 host 配置:
xx.xx.xx.xx(ip) hostname
再次 ping hostname 的效果就和直接 ping ip 一样了。
于是我再次重启应用,一切都正常了。
总结
最后根据我调整的内容尝试分析下本次问题的原因:
- 当
Dubbo在启动获取本地 ip 时,是通过服务器hostname从dns服务器返回当前的 ip 地址。 - 由于
dns服务器或者是本地服务器与 dns 服务器之间存在网络问题,导致这个过程的时间被拉长(猜测)。 - 我在本地的
host文件中配置后,就相当于本地有一个缓存,优先取本地配置的 ip ,避免了和 dns 服务器交互的过程,所以速度提升了。
虽然问题得到解决了,但还是有几个疑问:
第一个是为什么和 DNS 服务器的交互会这么慢,即便是慢也没有像应用那样需要 2 个小时才能返回,这里我也没搞得太清楚,有相关经验的朋友可以留言讨论。
第二就是 Dubbo 在这个依赖外部获取资源时健壮性是否可以做的更好,虽说我这问题估计也几人碰到。
对于这种长时间没有启动成功的问题是否可以加上提示,比如直接抛出异常退出程序,将问题可能的原因告诉开发者,方便排查问题。
你的点赞与分享是对我最大的支持
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
(4) 基于领域分析设计的架构规范 - 充血模型之实体
本系列目录: 改变与优势 领域分析基础 读写隔离 充血模型之实体 充血模型之Service 关于重构与落地 读写隔离后的世界 基于上面提到的读写隔离的思想,那么我们可以很清楚地看到上面这种情况可以看到: 查询业务,从入口层(如Controller),调用Finder,而Finder调用Repository(具体实现如Hiberante,Mybatis等等均可),这一条线下来,我们全然不用考虑这个系统的增删改就是如何做的,就像他们完全处于不同的空间一样,互不干涉,互不影响,甚至,永远互不相见。 某种程度上来说,这种这种架构追求的效果,一种美感。 所以,接下来,我们关注的,就是增删改这一部分了,也就是命令操作 是开始要扎扎实实地来对这个系统进行修改了 首先让我们把视野抬高一些,从整个项目产品的上空来看看 业务灵魂-状态图 除开少数非常扁平的纯技术服务项目(比如AI识别,文本分析等等),其他绝大部分企业项目都有其核心的商业逻辑,而这些逻辑,往往也会以核心的领域概念来提现,从简单粗暴一点角度映射到设计开发中,那就是类class 电商系统,核心领域至少有【商品】,【订单】,【用户】,【物流】等;...
-
下一篇
域名解析 域名控制台+极客+cloudflare 的配置方法
准备工作 由于使用goproxy的过程,ws传输协议可以利用CDN。本文综合的介绍了cloudflare注册使用,从域名解析到回源,完成了一个二级域使用cloudflare的CDN加速的配置过程。 首先你要去 cloudflare 官网https://dash.cloudflare.com/sign-up注册一个账号,然后登录,提示你添加域名的时候,不要添加,略过即可。 操作步骤 前提有一顶级域名domain.com,有一VPS,IP地址为111.222.111.222,要求二级域名test.domain.com指向上述IP地址。 1、在域名domain.com服务器上进行解析 例如: 主记录:vps1 记录类型:A 记录值:111.222.111.222 2、登陆https://su.geekzu.org平台 3、点击编辑-》添加-》填写二级域名test,和回源地址:vps.domain.com到相应的位置-》提交 4、提交后会看到如下: 这时域名test.domain.com 回源地址:vps1.domain.com CNAME地址:test.domain.com.cdn.clou...
相关文章
文章评论
共有0条评论来说两句吧...








微信收款码
支付宝收款码