问题背景
访问某个 HTTP 域名接口时,如果偶发性超时,原因可能很多:DNS 解析慢、网络质量抖动、对端服务负载高、客户端连接池异常,或者中间代理链路有问题。
在客户端没有良好埋点的情况下,这类问题很难一次定位,只能沿着“DNS -> 网络 -> 对端服务 -> 客户端实现”逐个排查。本文介绍一个小工具 dns-lookup-latency,用于快速采样域名 DNS 解析延迟,先判断 DNS 是否值得继续深挖。
它适合回答两个问题:
- 某个域名的解析耗时是否稳定?
- 偶发超时发生时,DNS 解析是否同时出现明显抖动?
使用演示
运行工具并传入域名,就会开始探测。默认每秒探测一次;如果想控制频率,可以传入第二个参数,例如 0.2 表示每 0.2 秒探测一次。
ulric@ulric-flashcat dns-lookup-latency % ./dns-lookup-latency baidu.com 0.2
Apr 7 09:25:15.414 : 26.060 ms
Apr 7 09:25:15.641 : 3.505 ms
Apr 7 09:25:15.846 : 4.584 ms
Apr 7 09:25:16.051 : 1.515 ms
Apr 7 09:25:16.253 : 6.028 ms
Apr 7 09:25:16.460 : 3.329 ms
Apr 7 09:25:16.665 : 2.943 ms
Apr 7 09:25:16.869 : 3.513 ms
Apr 7 09:25:17.073 : 1.969 ms
Apr 7 09:25:17.276 : 2.194 ms
Apr 7 09:25:17.480 : 2.394 ms
Apr 7 09:25:17.683 : 2.211 ms
Apr 7 09:25:17.886 : 3.497 ms
Apr 7 09:25:18.090 : 3.816 ms
Apr 7 09:25:18.294 : 1.672 ms
Apr 7 09:25:18.496 : 2.913 ms
Apr 7 09:25:18.700 : 2.693 ms
Apr 7 09:25:18.904 : 2.640 ms
输出里,冒号前面是时间戳,冒号后面是 DNS 解析延迟,单位是毫秒。
对于内网域名解析,延迟通常应该比较小。如果采样过程中出现明显毛刺,例如平时只有几毫秒,但偶发变成几十毫秒甚至更高,就可以把 DNS 链路作为重点排查对象。
需要注意,DNS 解析慢只能说明“域名解析阶段可能有问题”,不能直接证明 HTTP 接口超时一定由 DNS 引起。更稳妥的做法是把工具输出时间点和客户端超时日志、网络探测、服务端访问日志放在一起比对。
工具源码
这个需求比较简单,也可以用 shell 实现。这里使用 Go 实现,核心调用是 net.LookupIP。源码如下:
package main
import (
"fmt"
"net"
"os"
"strconv"
"time"
)
func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: %s <domain> <interval-seconds>\n", os.Args[0])
os.Exit(1)
}
domain := os.Args[1]
interval := 1.0
if len(os.Args) == 3 {
f, err := strconv.ParseFloat(os.Args[2], 64)
if err != nil {
fmt.Printf("failed to parse interval(%s): %v\n", os.Args[2], err)
os.Exit(1)
}
interval = f
}
duration := time.Millisecond * time.Duration(interval*1000)
for {
resolveDomain(domain)
time.Sleep(duration)
}
}
func resolveDomain(domain string) {
startTime := time.Now()
_, err := net.LookupIP(domain)
elapsed := time.Since(startTime)
if err != nil {
fmt.Printf("%v : %v\n", startTime.Format(time.StampMilli), err)
return
}
fmt.Printf("%v : %.3f ms\n", startTime.Format(time.StampMilli), elapsed.Seconds()*1000)
}
不到 50 行代码,逻辑很直接:
- 从命令行读取域名。
- 可选读取探测间隔,默认 1 秒。
- 循环调用
net.LookupIP(domain)。 - 记录调用前后的时间差。
- 成功时输出解析耗时,失败时输出错误。
另外,我给大家打包好了二进制文件,可以直接下载使用:
排查时怎么用
建议按下面步骤使用这个工具:
- 先在出现问题的客户端机器上运行,而不是只在本机运行。
- 探测业务实际访问的域名,不要只测公共域名。
- 让采样覆盖一段完整的故障窗口。
- 同步保留 HTTP 客户端超时日志,方便按时间戳对齐。
- 如果 DNS 延迟有毛刺,再继续检查本机 resolver、内网 DNS、递归 DNS、缓存策略和网络链路。
| 现象 | 初步判断 |
|---|---|
| DNS 延迟稳定,HTTP 仍超时 | 继续排查网络、对端服务或客户端连接池 |
| DNS 延迟偶发升高,HTTP 超时同时间出现 | DNS 链路值得重点排查 |
net.LookupIP 直接报错 |
检查域名、解析器配置和 DNS 服务可用性 |
FAQ
Q1:这个工具能替代完整的 DNS 监控吗? 不能。它适合临时采样和排障验证。长期监控还需要固定探测点、指标采集、告警和历史趋势。
Q2:为什么要在故障客户端机器上执行? DNS 配置、网络出口、缓存和本地 resolver 可能因机器或机房不同而不同。只有在真实客户端环境执行,结果才更接近业务请求路径。
Q3:只看 DNS 延迟就能定责吗? 不建议。DNS 延迟是证据之一,还要和 HTTP 超时、网络质量、服务端负载、日志时间戳一起分析。
附
如上知识,希望对你有帮助。文末请允许我插播一个小广告。本人创业两年了,我们公司的业务如下,如果你有这方面的需求,欢迎联系我们做产品技术交流哈。
🎯 关于快猫星云
快猫星云是一家云原生智能运维科技公司,由知名开源项目“夜莺(Nightingale)”的核心开发团队组成,创始团队均来⾃阿⾥、百度、滴滴等互联⽹公司。夜莺是一款开源云原生监控工具,是中国计算机学会接受捐赠并托管的第一个开源项目,在GitHub上有超过8000颗星,迭代发布了超过100多个版本,上百位社区贡献者,是国内领先的开源可观测性解决方案。
快猫星云以开源夜莺为内核打造的“Flashcat平台”,是国内顶级互联⽹公司可观测性实践的产品化落地,致力于让可观测性技术更好的服务企业,保障服务稳定性。Flashcat 平台具有以下特点:
- 统一采集:采用插件化思路,内置集成上百种采集插件,服务器、网络设备、中间件、数据库、应用、业务,均可监控,开箱即用。
- 统一告警:支持几十种数据源对接,收集各类监控系统的告警事件,进行统一的告警收敛、降噪、排班、认领、升级、协同,大幅提升告警处理效率。
- 统一观测:将 Metrics、Logs、Traces、Events、Profiling 等多种可观测性数据融会贯通,并预置行业最佳实践,既提供全局业务视角、技术视角的驾驶舱,也提供层层下钻的故障定位能力,有效缩短故障发现和定位时间。
