net.DialTimeout 是最轻量的 TCP 连通性检测方式,仅完成三次握手,需按网络场景设合理超时(局域网300–500ms、同地域800ms–1.2s、跨地域2–3s),避免误判。
如何用 net.DialTimeout 判断目标服务是否可达
单纯靠 ping 无法反映应用层连通性,比如 HTTP 服务端口开着但进程已挂。更可靠的方式是尝试建立 TCP 连接。net.DialTimeout 是最轻量的检测入口,它不发送任何应用层数据,只完成三次握手。
常见错误是把超时设得太长(如 30 秒),导致监控毛刺明显;或设得太短(如 100ms),在高延迟网络下误判。建议按场景分级:
- 局域网内服务探测:300–500ms
- 同地域云服务器:800ms–1.2s
- 跨地域或公网 API:2–3s(需配合重试)
示例代码片段:
conn, err := net.DialTimeout("tcp", "example.com:80", 2*time.Second)
if err != nil {
// 连接失败,可能是端口关闭、防火墙拦截、DNS 不可达等
log.Printf("failed to dial: %v", err)
return false
}
defer conn.Close()
return true
为什么 http.Get 返回 200 不代表服务健康
http.Get 成功只说明 HTTP 协议栈响应了,但可能返回的是 Nginx 默认页、维护中页面、甚至 CDN 缓存的 200 响应。真实业务健康需要校验响应内容或状态码语义。
关键点在于:必须设置 http.Client.Timeout,否则默认无超时,一次失败会卡住整个监控 goroutine;同时禁用重定向,避免跳转掩盖原始状态: