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 时,是通过服务器 hostnamedns 服务器返回当前的 ip 地址。


  • 由于 dns 服务器或者是本地服务器与 dns 服务器之间存在网络问题,导致这个过程的时间被拉长(猜测)。


  • 我在本地的 host 文件中配置后,就相当于本地有一个缓存,优先取本地配置的 ip ,避免了和 dns 服务器交互的过程,所以速度提升了。


虽然问题得到解决了,但还是有几个疑问:


第一个是为什么和 DNS 服务器的交互会这么慢,即便是慢也没有像应用那样需要 2 个小时才能返回,这里我也没搞得太清楚,有相关经验的朋友可以留言讨论。


第二就是 Dubbo 在这个依赖外部获取资源时健壮性是否可以做的更好,虽说我这问题估计也几人碰到。


对于这种长时间没有启动成功的问题是否可以加上提示,比如直接抛出异常退出程序,将问题可能的原因告诉开发者,方便排查问题。


相关文章
|
XML Dubbo Java
【Dubbo3高级特性】「框架与服务」服务的异步调用实践以及开发模式
【Dubbo3高级特性】「框架与服务」服务的异步调用实践以及开发模式
349 0
|
Dubbo Java 应用服务中间件
Dubbo服务暴露机制解密:深入探讨服务提供者的奥秘【九】
Dubbo服务暴露机制解密:深入探讨服务提供者的奥秘【九】
164 0
|
缓存 运维 监控
Dubbo服务降级:保障稳定性的终极指南【六】
Dubbo服务降级:保障稳定性的终极指南【六】
306 0
|
Dubbo Java 应用服务中间件
Spring Boot Dubbo 构建分布式服务
Spring Boot Dubbo 构建分布式服务
187 0
|
SpringCloudAlibaba Dubbo Java
SpringCloud Alibaba集成Dubbo实现远程服务间调用
SpringCloud Alibaba集成Dubbo实现远程服务间调用
|
Dubbo 前端开发 Java
Dubbo3 服务原生支持 http 访问,兼具高性能与易用性
本文展示了 Dubbo3 triple 协议是如何简化从协议规范与实现上简化开发测试、入口流量接入成本的,同时提供高性能通信、面向接口的易用性编码。
16979 108
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
816 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
JSON Dubbo Java
【Dubbo协议指南】揭秘高性能服务通信,选择最佳协议的终极攻略!
【8月更文挑战第24天】在分布式服务架构中,Apache Dubbo作为一款高性能的Java RPC框架,支持多种通信协议,包括Dubbo协议、HTTP协议及Hessian协议等。Dubbo协议是默认选择,采用NIO异步通讯,适用于高要求的内部服务通信。HTTP协议通用性强,利于跨语言调用;Hessian协议则在数据传输效率上有优势。选择合适协议需综合考虑性能需求、序列化方式、网络环境及安全性等因素。通过合理配置,可实现服务性能最优化及系统可靠性提升。
268 3
|
缓存 Dubbo Java
Dubbo服务消费者启动与订阅原理
该文章主要介绍了Dubbo服务消费者启动与订阅的原理,包括服务消费者的启动时机、启动过程以及订阅和感知最新提供者信息的方式。
Dubbo服务消费者启动与订阅原理
|
Dubbo 网络协议 Java
深入掌握Dubbo服务提供者发布与注册原理
该文章主要介绍了Dubbo服务提供者发布与注册的原理,包括服务发布的流程、多协议发布、构建Invoker、注册到注册中心等过程。
深入掌握Dubbo服务提供者发布与注册原理