跳转至

网络排障

学习目标

学完本章后,学习者应该能够:

  1. 掌握 ping、traceroute、curl、nc、dig、ss、tcpdump 的基本用途。
  2. 能按 DNS、TCP、TLS、HTTP、应用处理分层排查超时。
  3. 能读懂常见网络错误信息。
  4. 能写出生产网络问题的排查记录。

排障思路

不要一上来猜。先把问题拆成阶段:

  1. 域名是否能解析?
  2. 目标 IP 是否可达?
  3. TCP 端口是否能连接?
  4. TLS 握手是否成功?
  5. HTTP 状态码是什么?
  6. 请求是否到达应用?
  7. 应用是否卡在下游依赖?

每一步都要用工具或日志验证。

常用工具

工具 用途
ping 粗略测试连通性和延迟
traceroute / tracert 查看路由路径
curl 测试 HTTP / HTTPS
telnet / nc 测试 TCP 端口连通性
dig / nslookup 测试 DNS
ss / netstat 查看连接和监听状态
tcpdump 抓包分析

常见错误

错误 可能方向
no such host DNS 解析失败
connection refused 端口未监听或被拒绝
connection timed out 网络不通、防火墙、服务无响应
connection reset by peer 对端重置连接
TLS handshake timeout TLS 握手慢或失败
context deadline exceeded Go context 超时
i/o timeout 网络 IO 超时

Go 后端实际应用例子

例子一:给错误打上阶段标签

func FetchJSON(ctx context.Context, client *http.Client, url string) error {
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    if err != nil {
        return fmt.Errorf("build request: %w", err)
    }

    resp, err := client.Do(req)
    if err != nil {
        return fmt.Errorf("do request: %w", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode >= 500 {
        return fmt.Errorf("upstream status: %d", resp.StatusCode)
    }
    return nil
}

错误信息要让排障者知道失败阶段,而不是只返回“请求失败”。

例子二:记录关键网络字段

调用外部服务时建议记录:

  • target host。
  • method。
  • status code。
  • latency。
  • error type。
  • retry count。
  • request id。

这些字段能帮助你在事故时快速区分是网络、代理、下游服务还是自身问题。

跨平台命令

Test-NetConnection example.com -Port 443
nslookup example.com
tracert example.com
netstat -ano
curl.exe -v https://example.com
nc -vz example.com 443
dig example.com
traceroute example.com
ss -antp
curl -v https://example.com

常见误区

  • 误区一:只看应用日志。

请求可能根本没到应用。代理日志、负载均衡日志、DNS、TCP 和 TLS 都要看。

  • 误区二:只看平均延迟。

网络问题常表现为长尾延迟和偶发失败。P95、P99、错误率更关键。

  • 误区三:排障命令能替代监控。

命令适合现场验证,生产系统仍需要持续指标、日志和链路追踪。

线上问题案例

某 API 偶发 context deadline exceeded。一开始怀疑 Go 服务慢,但链路追踪显示请求卡在调用 Redis。继续查看 Redis 连接池指标,发现连接池耗尽,请求排队等待连接。

修复方式是调整连接池、减少慢命令、增加超时指标,并在日志中区分“连接池等待耗时”和“Redis 执行耗时”。

实战任务

给出“访问 https://api.example.com 超时”的排查步骤:

  1. 检查 DNS。
  2. 检查 TCP 端口。
  3. 检查 TLS。
  4. 检查 HTTP 状态。
  5. 检查应用日志和代理日志。
  6. 记录结论和下一步。
参考答案

先用 dignslookup 确认域名能解析,并记录解析 IP。再用 ncTest-NetConnectioncurl -v 检查 443 端口是否可连。curl -v 可以观察 TLS 握手和 HTTP 状态码。

如果请求没有到应用日志,重点看负载均衡、网关、防火墙、安全组、证书和路由。如果应用收到请求但处理慢,继续看应用耗时分段、下游依赖、数据库、缓存和连接池。排障记录要写明每一步证据,而不是只写“网络问题”。

面试题

1. connection refused 和 connection timed out 有什么区别?

参考答案

connection refused 通常表示目标主机可达,但目标端口没有服务监听,或主动拒绝连接。connection timed out 通常表示连接请求没有得到响应,可能是网络不通、防火墙丢包、安全组拦截或服务严重无响应。

两者排查方向不同:refused 先看监听端口和服务状态;timeout 先看路由、防火墙、安全组和网络连通性。

2. curl -v 能帮助观察什么?

参考答案

curl -v 可以显示 DNS 结果、连接目标、TLS 握手、请求 Header、响应 Header 和状态码等信息。

它适合快速判断问题发生在 DNS、TCP、TLS、HTTP 还是应用响应阶段。

3. tcpdump 适合什么时候使用?

参考答案

tcpdump 适合在日志和普通命令无法解释问题时抓包验证,例如确认是否发出了 SYN、是否收到 SYN+ACK、是否有重传、RST、TLS 握手失败或包被发送到错误地址。

抓包成本较高,生产环境使用时要控制过滤条件、时间和数据量,避免采集敏感信息。