当前位置: 首页 > news >正文

一次由 DNS 反解析引发的 SpringBoot 启动卡顿问题

TL;DR

使用 114 DNS 时,反解析内网 IP 无响应,导致 SpringBoot 启动时 Liquibase 初始化阻塞约 30 秒

InetAddress.getLocalHost() 获取到的可能是127.0.0.1,而非实际的内网 IP(如 192.168.x.x)

现象

SpringBoot启动时(HikariPool 初始化后)卡顿 30s

2025-11-09 15:14:33 INFO [main] com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...

2025-11-09 15:14:33 INFO [main] com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection com.p6spy.engine.wrapper.ConnectionWrapper@7f6137fb

2025-11-09 15:14:33 INFO [main] com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.

排查

通过 jstack 分析线程栈,定位到 liquibase.util.NetUtil.getLocalHostName() 阻塞

# jps

jstack 66713

下方线程栈显示阻塞点位于 Inet6AddressImpl.getHostByAddr()

"main" #1 prio=5 os_prio=31 cpu=3549.34ms elapsed=14.86s tid=0x000000010a808200 nid=0xd03 runnable [0x000000016fa00000]

java.lang.Thread.State: RUNNABLE

at java.net.Inet6AddressImpl.getHostByAddr(java.base@17.0.14/Native Method)

at java.net.InetAddress$PlatformNameService.getHostByAddr(java.base@17.0.14/InetAddress.java:940)

at java.net.InetAddress.getHostFromNameService(java.base@17.0.14/InetAddress.java:662)

at java.net.InetAddress.getHostName(java.base@17.0.14/InetAddress.java:605)

at java.net.InetAddress.getHostName(java.base@17.0.14/InetAddress.java:577)

at liquibase.util.NetUtil.getLocalHostName(NetUtil.java:79)

at liquibase.sqlgenerator.core.LockDatabaseChangeLogGenerator.<clinit>(LockDatabaseChangeLogGenerator.java:30)

对应源码:

public class LockDatabaseChangeLogGenerator extends AbstractSqlGenerator<LockDatabaseChangeLogStatement> {

@Override

public ValidationErrors validate(LockDatabaseChangeLogStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {

return new ValidationErrors();

}

protected static final String hostname;

protected static final String hostaddress;

protected static final String hostDescription = (System.getProperty("liquibase.hostDescription") == null) ? "" :

("#" + System.getProperty("liquibase.hostDescription"));

static {

try {

// NetUtil.getLocalHostName() 导致阻塞

hostname = NetUtil.getLocalHostName();

hostaddress = NetUtil.getLocalHostAddress();

} catch (Exception e) {

throw new UnexpectedLiquibaseException(e);

}

}

// ...

}

分析

NetUtil.getLocalHostName() 获取机器 IP:遍历网卡,调用 InetAddress.getHostName() 对内网 IP (192.168.10.2)做反解析,114 DNS(114.114.114.114)无响应,则导致阻塞 30s

package liquibase.util;

// ...

public class NetUtil {

// ...

/**

* @return Machine's host name. This method can be better to call than getting it off {@link #getLocalHost()} because sometimes the external address returned by that function does not have a useful hostname attached to it.

* This function will make sure a good value is returned.

*/

public static String getLocalHostName() {

if (hostName == null ) {

try {

// 遍历所有网络接口,找出 已启用 的 非点对点 网络接口,然后打印这些接口上每个非本地地址对应的主机名(hostname)

InetAddress localHost = getLocalHost();

if(localHost != null) {

// 使用指定的 DNS 反解析获取的 IP

hostName = localHost.getHostName();

if (hostName.equals(localHost.getHostAddress())) {

//sometimes the external IP interface doesn't have a hostname associated with it but localhost always does

InetAddress lHost = InetAddress.getLocalHost();

if (lHost != null) {

hostName = lHost.getHostName();

}

}

}

else {

hostName = UNKNOWN_HOST_NAME;

}

} catch (Exception e) {

Scope.getCurrentScope().getLog(NetUtil.class).fine("Error getting hostname", e);

if (hostName == null) {

hostName = UNKNOWN_HOST_NAME;

}

}

}

return hostName;

}

}

大多数公共 DNS(如阿里、Google)在无法解析内网地址时返回 NXDOMAIN,而 114 DNS 无响应,导致 Java 原生反解析方法阻塞

# 耗时:0.228s

nslookup 192.168.10.2 223.5.5.5

Server: 223.5.5.5

Address: 223.5.5.5#53

** server can't find 2.10.168.192.in-addr.arpa: NXDOMAIN

# 耗时:15.137s

nslookup 192.168.10.2 114.114.114.114

;; connection timed out; no servers could be reached

遍历网卡的原因

获取机器 IP 常用的方法:InetAddress.getLocalHost() 获取到的可能是127.0.0.1(与 JDK 实现有关),是一个本地回环地址(loopback address)。而非对外通信用的实际的网络 IP(例如 192.168.x.x 或 10.x.x.x)

为了获取 实际的网络 IP,一般使用类似上面 NetUtil.getLocalHostName() 的方式,遍历网卡获取实际 IP

http://www.cnnetsun.cn/news/49034.html

相关文章:

  • 后端学习笔记
  • Gitea权限管理:构建安全高效的代码访问控制体系
  • AI视频生成终极指南:从零开始快速上手WAN2.2-14B-Rapid-AllInOne
  • Ascend C 编译器内幕与自动调优实战:从手写 Kernel 到 AI 驱动的性能优化
  • Ascend C 绿色计算与边缘部署:面向低碳 AI 的极致能效优化实践
  • Step-Audio 2系列深度实战指南:多模态音频理解的技术突破与应用全景
  • 量子计算终极指南:如何用Qiskit快速掌握量子编程的完整教程
  • React-chartjs-2 实战深度突破:从数据混沌到可视化洞察的架构思维
  • 22、LTSP 环境搭建与 Ubuntu 服务器安全指南
  • 23、Linux系统安全管理:sudo、AppArmor与SSH的深度解析
  • 智能中文对话系统完整构建指南:从零到一的5个关键步骤
  • Java泛型实战:类型安全与高效开发
  • 无需函数,教你快速分离Excel单元格中的文本和数字
  • 学术探索新航标:书匠策AI解锁毕业论文写作的“隐形导航仪”
  • 告别论文“缝合怪”:解锁书匠策AI,把信息碎片织成你的知识图谱
  • 学术迷航中的智能灯塔:书匠策AI如何重构毕业论文写作生态
  • 别再死磕论文了!你的毕业论文需要一个“科研副驾”
  • 当你的学术世界支离破碎,我借AI之手为它重绘版图
  • 论文焦虑终结者?揭秘「书匠策AI」如何用算法重构你的学术写作体验
  • 职场进阶:如何全面提升面试表现力?
  • 律师咨询|基于springboot + vue律师咨询系统(源码+数据库+文档)
  • Agent 通过Langchain实现网页检索功能
  • 终极指南:5分钟快速搭建个人作品集网站的完整解决方案
  • CogVideo革命性突破:2D视频秒变立体3D的智能转换技术
  • DeepLabCut实战进阶:从姿态估计到强化学习环境的深度配置指南
  • 终极游戏DLC解锁指南:三步免费解锁付费内容
  • SeedVR2 2.5.10全面评测:8GB显存也能玩转的AI视觉增强神器
  • PCSX2模拟器性能优化终极指南:从卡顿到流畅的完整解决方案
  • 告别卡顿:DBeaver性能优化终极指南
  • NetSonar网络诊断工具:快速定位网络问题的终极解决方案