一次连接超时问题排查的历程
这是一次典型的、从迷茫到顿悟的故障排查历程。作者从一个Java应用启动时偶尔发生、且目标服务器不固定的数据库连接超时问题出发,展开了一场层层深入的调查。 排查始于网络抓包,但发现了更怪异的现象:部分TCP连接的SYN包似乎从未发出,而另一些则在收到服务器SYN/ACK后被客户端立即RST。通过strace工具,作者确认了所有connect系统调用均已执行,超时发生在内核的poll等待阶段,这解释了RST的由来,但问题的源头——从系统调用到网络发包之间那段莫名的“延迟”——依然成谜。 对内核网络栈的初步探索未果后,一次未过滤ARP包的抓包带来了转机。作者发现,连接失败的IP地址对应的ARP请求首次均无响应,需等待1秒后重试才成功。这1秒的延迟,足以让设定为50毫秒的连接超时大量失败。根因在于局域网存在广播限流,导致启动时ARP请求被丢弃,而一旦应用启动成功,持续的通信就会维持ARP缓存,故运行时再无此问题。 从复杂内核栈排查到基础的ARP缓存,作者也感慨这个原因“如此操蛋没技术含量”。但这个过程生动地说明,面对诡异的系统问题,保持开放的排查思路,并扎实地追踪数据流的每一环,是定位真相的关键。