网络课本里的箭头很整齐,浏览器、DNS、TCP、HTTP 一层层向下。实际排错时,问题经常出在这些箭头之间:域名已经解析了,连接却被拒绝;TCP 已经建立,HTTP 仍然返回错误;页面能打开,另一个请求却被跨域策略挡住。
我先把几条常见边界重新画了一遍。DNS 负责把名字解析成地址,不负责证明服务一定可用;TCP 负责可靠的字节流,不知道“请求”在哪里结束;HTTP 负责语义和头部,不保证应用一定返回正确业务结果。把它们写成一件事,调试时就会少掉很多错误的假设。
三次握手确认的是双方建立连接的能力,不是应用已经准备好。连接建立以后,还可能遇到 TLS、代理、反向代理和应用路由。四次挥手和 TIME_WAIT 也不是“多等一会儿”这么简单,它们与延迟报文和连接复用有关;调整内核参数以前,先确认瓶颈在哪里。
HTTP/2 的多路复用解决了多个请求争抢 TCP 连接的问题,但 TCP 层的丢包仍会影响同一条连接上的数据。HTTP/3 把传输换成 QUIC,流之间的影响更小,代价是部署、观测和中间设备兼容又多了一层。写表格时最好标注“协议能力”和“实际部署条件”,不要把“支持”写成无条件的结论。
DNS 解析也不是一条固定路线。浏览器、操作系统、路由器和递归解析器都可能缓存结果,权威服务器只在链路的一端。改完记录以后,某台机器仍解析到旧地址,不一定是 DNS 服务坏了,可能只是 TTL 尚未过期。排查时把查询来源和缓存层写出来,比反复刷新页面更有效。
网络学习最有用的产物是一份问题清单:请求停在哪一层,能不能用命令复现,响应头和日志是否相互印证,换一个网络会不会改变结果。层次越清楚,报错越不容易被一句“网络问题”吞掉。
这些基础知识不会让每次请求都成功,却会让失败变得可定位。那张图的价值不在于它看起来完整,而在于它能指向下一条该检查的线。
排错时我会把每一层的证据放在同一张表里:解析结果、连接地址、TLS 握手、请求头、响应码和应用日志。这样不会因为某一层正常就提前结束,也能把“偶发”问题变成可以比较的样本。
网络排错的记录最好能复用。命令、时间、解析地址、连接耗时和响应头放在同一份样本里,下一次遇到相似问题时可以直接比较。这样“偶发打不开”才有机会变成某一层在某个时间段发生了变化。
我也会把代理、CDN 和应用日志分开保存。中间层返回 200 只说明它交付了一个响应,不说明源站完成了业务;只有把请求 ID 串起来,才能判断错误是在入口、转发还是应用内部产生的。
网络图里容易遗漏的,往往并非节点数量,更多是边的含义。把节点、边、方向和失败状态分开画出来,很多“看起来连通”的假设才会暴露。