网络协议栈与 DNS — 分层定位,一次只查一层

一句话:网络故障的定位永远是「分层二分」——先确认能不能到(网络层),再确认端口通不通(传输层),最后才看应用逻辑(应用层);跨层猜原因只会浪费时间。

🎯 这 20% 能解决哪些问题

你遇到的困惑本质原因马上能改的动作
网页打不开,不知道从哪查起没有分层排查思路按 dig → ping → telnet/curl → 服务端日志 四步走
服务器大量 TIME_WAIT,端口耗尽短连接频繁开关改长连接/连接池,或开启 tcp_tw_reuse 并加端口范围
接口偶发超时,重试就好重传与拥塞控制在起作用,或链路丢包看 retrans 指标与 RTT,而不是只加超时时间
域名改了记录,部分用户还是老地址各级 DNS 缓存与 TTL提前把 TTL 降到 60s,改完查 dig +trace
内网两台机器互相不通安全组/路由/防火墙,而不是应用先确认同网段与路由表,再查安全组规则
WebSocket/音视频卡、延迟敏感用 TCP 扛丢包,队头阻塞明确 UDP/QUIC 场景,别用 TCP 传实时流

一、四层模型:每层只解决一个问题

flowchart TB
    subgraph S1["应用层:说什么"]
        A["HTTP / DNS / TLS / WebSocket"]
    end
    subgraph S2["传输层:端到端是否可靠"]
        T["TCP(可靠有序) / UDP(低延迟)"]
    end
    subgraph S3["网络层:走哪条路"]
        N["IP 寻址 + 路由 + ICMP"]
    end
    subgraph S4["链路层:这一跳怎么传"]
        L["以太网 / WiFi / ARP"]
    end
    A --> T --> N --> L
层关键标识排查看什么典型故障
应用层域名、URL、状态码响应头、证书、日志502、证书过期、重定向环
传输层IP + 端口连接数、重传、队列端口未监听、SYN 被丢、连接耗尽
网络层IP 地址路由表、安全组、MTU跨网段不通、分片被丢
链路层MACARP、交换机、无线信号同段不通、DNS 解析慢

核心规律:数据只能「一层层包起来,一层层剥开」。任何一层的地址缺失或规则拦截,表现都是「连不上」,但原因完全不同。


二、TCP:可靠性由四个机制撑起

2.1 连接生命周期

sequenceDiagram
    participant C as 客户端
    participant S as 服务端
    C->>S: SYN(进入连接请求队列)
    S->>C: SYN+ACK
    C->>S: ACK(连接建立,进入 ESTABLISHED)
    Note over C,S: 数据传输(滑动窗口 + 确认号)
    C->>S: FIN
    S->>C: ACK
    S->>C: FIN
    C->>S: ACK(主动关闭方进入 TIME_WAIT,持续 2MSL)
状态/现象含义处置
大量 SYN_RECV半连接队列被打满,疑似 SYN 洪泛开 SYN cookie、限流、加队列
大量 TIME_WAIT本端主动关闭且连接频繁用长连接/连接池,扩大 ip_local_port_range
大量 CLOSE_WAIT对端已关,本端没 close()代码 bug:检查连接/流是否释放
RST端口没监听或被中间设备拒绝检查监听地址、安全组、负载均衡健康检查

2.2 四个机制

机制解决什么实用结论
序列号 + 确认乱序与丢失「可靠」不等于「不丢包」,丢包靠重传补
滑动窗口快慢匹配,不压垮慢端窗口为 0 表示接收端处理不过来,问题在应用
拥塞控制不挤爆共享链路慢启动→拥塞避免→丢包后回退,解释了「越丢越慢」
超时重传黑洞链路RTO 动态估算;一次超时会让延迟跳变

带宽 × 延迟决定吞吐上限:理论吞吐 ≈ 窗口大小 ÷ RTT。跨洋高延迟链路想跑满带宽,必须放大窗口(tcp_window_scaling)。


三、UDP 与 QUIC:什么时候不要可靠传输

传输特点适用代价
TCP有序、可靠、阻塞式网页、API、文件、数据库队头阻塞;丢包重传增加尾延迟
UDP无连接、不保证到达直播、语音、DNS 查询、游戏状态应用自己做序号与丢包容错
QUIC (HTTP/3)UDP 之上做可靠 + 每流独立 + 0-RTT弱网、移动端、多路复用CPU 开销更高,运维观测门槛高

判据:能容忍丢包但不能容忍等待 → UDP/QUIC;一条都不能错 → TCP。


四、IP、子网、NAT 与路由

概念必须记住的
私网段10.0.0.0/8、172.16.0.0/12、192.168.0.0/16;其余为公网
CIDR/24 = 256 个地址(可用 254),/16 = 65536
网关同网段直接 ARP 找 MAC;跨网段交给默认网关
路由选择最长前缀匹配:更具体的路由优先于 0.0.0.0/0
NAT私网访问公网时改写源地址与端口;NAT 之后的机器不可被主动连入
安全组/防火墙默认拒绝入站;出站规则常被忽略,是隐蔽故障源
flowchart LR
    A["应用发起 connect()"] --> B["DNS 解析域名"]
    B --> C["查路由表选出口"]
    C --> D{"同网段?"}
    D -->|"是"| E["ARP 找 MAC 直接发"]
    D -->|"否"| F["发给默认网关逐跳转发"]
    F --> G["NAT 改写源地址 / 出公网"]
    G --> H["对端回包沿原路返回"]

五、DNS:解析链与真实生效时间

sequenceDiagram
    participant B as 浏览器/系统
    participant R as 递归解析器
    participant root as 根域名服务器
    participant tld as 顶级域服务器
    participant au as 权威服务器
    B->>R: 查询 example.com
    R->>root: 谁管 .com
    root-->>R: 指向 .com 顶级域
    R->>tld: 谁管 example.com
    tld-->>R: 指向权威 NS
    R->>au: 要 A 记录
    au-->>R: 返回 IP(带 TTL)
    R-->>B: 结果并缓存
记录类型用途常见坑
A / AAAA域名 → IPv4 / IPv6只配 A 忘配 AAAA 会变慢
CNAME别名 → 规范名不能与 A 记录共存于同一名字;无法用于根域
MX / TXT邮件 / 验证与 SPFTXT 长度限制
NS谁权威迁移时 NS 未切,改记录无效

排查要点:dig +trace 看解析链路;dig @8.8.8.8 绕过本地缓存验证权威结果; hosts 文件优先级高于 DNS,是「本地正常别人不正常」的常见原因。


六、MTU 与分片:被丢的大包

值说明
1500 B以太网标准 MTU
1400–1460 BPPPoE/VPN 封装后可用载荷,常见「小请求正常、大请求卡住」的原因
ICMP「需要分片」被拦Path MTU 发现失败,表现为特定域名打不开

处置:VPN/容器网络出现「握手成功但数据不通」,先把 MSS clamp 到 1360–1400 验证是否是 MTU 问题。


七、排查工具链:按层选择

症状命令看什么
域名解析对不对dig example.com +noall +answer返回 IP 与 TTL 是否符合预期
网络层是否可达ping -c 5 host丢包率与 RTT 稳定性(不是快慢)
卡在哪一跳traceroute -T -p 443 host用 TCP 探测,避免 ICMP 被限速误判
端口是否监听ss -lntp / telnet host 6379LISTEN 地址是否 0.0.0.0 而非 127.0.0.1
连接状态堆积ss -s、ss -ant state time-waitTIME_WAIT/CLOSE_WAIT 数量含义见 2.1
完整 HTTP 过程curl -v -w '%{time_total}\n'DNS/连接/TLS/首字节各段耗时
抓包定责tcpdump -i any -nn port 443有无 SYN、有无 RST、是否重传
flowchart TD
    A["用户报「打不开」"] --> B{"dig 能解析?"}
    B -->|"否"| B1["检查 DNS 配置/hosts/权威 NS"]
    B -->|"是"| C{"ping 通?"}
    C -->|"否"| C1["检查路由、安全组、ICMP 是否被禁"]
    C -->|"是"| D{"端口能连?"}
    D -->|"否"| D1["检查服务监听地址、防火墙、负载均衡后端"]
    D -->|"是"| E["看应用日志与 curl -v 分段耗时"]

🎓 实战场景(TIL)

  • 场景:服务间 99% 请求很快,偶发 200ms 尖峰。本质:DNS 缓存过期后的解析往返,或 TCP 慢启动(新连接从头窗口开始)。要点:长连接 + 连接池复用,客户端侧保留 DNS 缓存,把尖峰对齐到「新建连接」这一事件上验证。
  • 场景:本地正常、容器集群里偶尔卡住。本质:overlay 网络额外头部让实际 MTU 小于 1500,大包被丢但 ICMP 又被屏蔽(PMTUD 黑洞)。要点:用 ping -s 1472 逐尺寸试探可用 MTU,调容器网络 MTU,不要只靠内核自动发现。
  • 场景:netstat 里几万条 TIME_WAIT,运维想调内核参数。本质:本端主动关闭的正常状态,它保护的是旧连接的重复分段。要点:先用长连接减少新建频率,再考虑 tcp_tw_reuse + 时间戳;乱改参数会牺牲正确性。
  • 场景:跨可用区一次请求多 30ms。本质:RTT 是物理距离决定的,重传至少多等一个 RTT。要点:区分「带宽不够」与「延迟高」:前者靠并行流,后者只能靠近用户部署或减少往返次数。

📋 一页速查

我要判断照着做
故障在哪一层dig → ping → 端口连通 → curl -v 分段,逐层二分
该用 TCP 还是 UDP不能丢 → TCP;不能等 → UDP/QUIC
TIME_WAIT 多正常(本端主动关闭);长连接 + 扩端口范围缓解
CLOSE_WAIT 多代码漏 close(),必须修
跨洋吞吐低带宽 × 延迟:吞吐 ≈ 窗口 ÷ RTT,放大窗口或加并发
改 DNS 何时生效看旧记录 TTL,各级缓存过期后才会更新
小请求正常大请求失败怀疑 MTU/MSS,VPN 与容器网络尤其常见
内网互访不通先查安全组入站规则与路由表,再查应用

🔗 相关链接