以下是当前正在使⽤的服务器环境
服务器: 华为云VPC
操作系统:CentOS 7
JDK版本: 1.8.0_151
SpringBoot版本: 1.5.8.Rlease
容器: Embedded Tomcat 8.5.23
⼀开始对这个问题,是忽略的,由于本⾝应⽤属于内部开发阶段,且每天更新和部署不是那么频繁等等因素,⼀直迟迟没有想去解决这个问题。不过最近因为临近项⽬上线,提交也⽐较多,⽽且因为应⽤拆分和前后端分离的问题,本地调试⽐较⿇烦,所以开始着⼿解决这个问题。
问题调查
⾸先看到这个异常,确实第⼀感觉是域名解析出的问题,于是考虑是不是Tomcat的域名解析服务出的问题,修改了EmbeddedTomcat的配修改之后测试发现问题依旧,去官⽹查了资料
其实Tomcat 8以后默认这个配置就是关闭的,这样看来⾃然就不是问题的根源了。
2. 重新梳理了⼀下思路,Spring Boot的初始化肯定是先于Tomcat的,所以应该是Spring Boot的初始化过程中出现了阻塞导致应⽤启动过慢
的问题。(不过要说明的是,知道此时并不确信是因为域名解析导致的阻塞,因为Spring Boot在启动过程中并没有抛出任何异常)
先做了个测试,启动Spring Boot应⽤的同时检查53端⼝,此时应⽤处于假死状态,应⽤和远程的DNS服务器正在通信,基本可以断定是因为调⽤了Jdk的InetAddress类的⽅法导致的问题。
于是通过jstack定位当前阻塞的代码
问题已经显⽽易见,Spring Boot在初始化的时候,执⾏了InetAddress的getLocalHost⽅法导致程序阻塞⽽影响了应⽤的启动时间。
SpringApplication
LoggingApplicationListener
LoggingSystemProperties
ApplicationPid
VMManagementImpl
⼜查看了⼀下当前服务器的DNS配置
可以看到DNS服务器的地址是公⽹的DNS地址,VPC访问不到导致取主机名的⽅法发⽣阻塞,因此导致应⽤启动时间⾮常长
问题解决
跟最初推测的差不多,确实是域名解析的问题,不过意外的是在Spring Boot初始化的时候获取VMID的时候会获取当前服务器的主机名。于是在/f中添加了本地主机的解析记录并删除⽆法访问的公⽹DNS配置,现在应⽤的启动已经和本地⼀样了
问题反思
服务器虽然最开始就定位了问题是DNS,不过发⽣问题的根源⼀直没有确定,也不想只是简单的把DNS配置修改来⽴刻解决问题,毕竟希望究本溯源,不希望被表⾯的问题所迷惑。
于是⼜查看了JDK的源码,发现InetAddress#getLocalHost是个本地⽅法
InetAddress
Inet4AddressImpl 本地⽅法也难不倒我们,下载了openjdk的源码到对应的C源码
这个⽅法来⾃于jvm.cpp⾥⾯的⽅法
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论