
【现象】
业务侧:系统用户登录接口,服务器里日志显示获取IP地址代码固定卡顿10秒。
技术侧:部署在linux的java springboot程序,获取IP地址时,偶尔出现接口卡顿约10秒,测试环境正常,仅生产服务器复现
【原因】
代码
import java.net.InetAddress;
//问题代码行
InetAddress inet = = InetAddress.getLocalHost();
这个方法在 Linux 生产环境下"会触发 DNS 反向解析,超时默认就是 10s",间歇性复现,测试机正常、生产卡,完全匹配现象。
【原理说明】
-
InetAddress.getLocalHost():底层会去 /etc/hosts 查找本机 hostname 对应的 IP;
-
如果服务器 /etc/hosts 没有配置 hostname → 127.0.0.1 映射,操作系统就会发起 DNS 查询去解析主机名;
-
DNS 服务器不可达 / 超时,阻塞等待,默认超时大约 10 秒;
-
间歇性:DNS 查询偶尔成功、偶尔超时,所以时而卡时而正常;
-
测试服务器:测试机 hosts 一般都配好了 hostname 映射,不会触发外网 DNS 查询,所以不卡顿。
触发时机:只有当拿到的 ip 是 0:0:0:0:0:0:0:1 或者 127.0.0.1 才会走进这段代码
【核心结论】
hosts 里有127.0.0.1 localhost,但是缺少【本机 hostname】映射。
InetAddress.getLocalHost() 不是查localhost,它查的是服务器主机名(hostname 命令输出的值),不是localhost字样。
【复现】
进入服务器
# 查看容器内主机名,并记录下来
hostname

# 测试这个阻塞API,直接模拟Java InetAddress.getLocalHost()
time getent hosts $(hostname)

实锤了!
getent hosts i-MpHmJ6NrA-5 稳定耗时 10s,完全确认根因:
Linux glibc 域名解析在查询主机名 i-MpHmJ6NrA-5 时,DNS 链路超时,正好 10 秒阻塞。Java InetAddress.getLocalHost() 底层就是调用这套系统调用,所以间歇性卡住 10 秒。
【快速修复】
(当前这台机器)
编辑 /etc/hosts,追加行(注意i-MpHmJ6NrA-5字样要替换成你自己服务器刚敲hostname命令记录的):
127.0.0.1 i-MpHmJ6NrA-5
::1 i-MpHmJ6NrA-5

保存后重新测试:
time getent hosts i-MpHmJ6NrA-5

解决了,困扰一周的问题,大功告成。
【建议上线顺序】
-
开发:修改代码,删除`InetAddress.getLocalHost()`这段阻塞逻辑,打包发布;推荐首选,永久根治,消除逻辑错误
-
应急:先在生产机器 /etc/hosts 加上 hostname 映射,临时缓解当前卡顿,作为过渡手段