从输入 URL 到页面返回:DNS、路由、TLS 与 HTTP 完整链路

在浏览器输入一个 HTTPS 地址后,页面并不是"直接从服务器下载"这么简单。浏览器可能先查缓存,再解析域名、寻找默认网关、建立传输连接、验证证书、协商加密参数,随后请求才可能经过 CDN、负载均衡和网关到达应用。

本文以访问 https://www.example.com/products?id=42 为例,把一次请求拆成可观测的阶段,并说明每一层常见的故障表现与排查方法。

1. 先看完整链路

一次典型访问可以抽象为以下路径。实际环境可能复用已有 DNS、TCP 或 HTTP 连接,因此并非每次都完整执行所有步骤。
#mermaid-svg-hgreuSua72SXOjJK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hgreuSua72SXOjJK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hgreuSua72SXOjJK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hgreuSua72SXOjJK .error-icon{fill:#552222;}#mermaid-svg-hgreuSua72SXOjJK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hgreuSua72SXOjJK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hgreuSua72SXOjJK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hgreuSua72SXOjJK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hgreuSua72SXOjJK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hgreuSua72SXOjJK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hgreuSua72SXOjJK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hgreuSua72SXOjJK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hgreuSua72SXOjJK .marker.cross{stroke:#333333;}#mermaid-svg-hgreuSua72SXOjJK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hgreuSua72SXOjJK p{margin:0;}#mermaid-svg-hgreuSua72SXOjJK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hgreuSua72SXOjJK .cluster-label text{fill:#333;}#mermaid-svg-hgreuSua72SXOjJK .cluster-label span{color:#333;}#mermaid-svg-hgreuSua72SXOjJK .cluster-label span p{background-color:transparent;}#mermaid-svg-hgreuSua72SXOjJK .label text,#mermaid-svg-hgreuSua72SXOjJK span{fill:#333;color:#333;}#mermaid-svg-hgreuSua72SXOjJK .node rect,#mermaid-svg-hgreuSua72SXOjJK .node circle,#mermaid-svg-hgreuSua72SXOjJK .node ellipse,#mermaid-svg-hgreuSua72SXOjJK .node polygon,#mermaid-svg-hgreuSua72SXOjJK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hgreuSua72SXOjJK .rough-node .label text,#mermaid-svg-hgreuSua72SXOjJK .node .label text,#mermaid-svg-hgreuSua72SXOjJK .image-shape .label,#mermaid-svg-hgreuSua72SXOjJK .icon-shape .label{text-anchor:middle;}#mermaid-svg-hgreuSua72SXOjJK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hgreuSua72SXOjJK .rough-node .label,#mermaid-svg-hgreuSua72SXOjJK .node .label,#mermaid-svg-hgreuSua72SXOjJK .image-shape .label,#mermaid-svg-hgreuSua72SXOjJK .icon-shape .label{text-align:center;}#mermaid-svg-hgreuSua72SXOjJK .node.clickable{cursor:pointer;}#mermaid-svg-hgreuSua72SXOjJK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hgreuSua72SXOjJK .arrowheadPath{fill:#333333;}#mermaid-svg-hgreuSua72SXOjJK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hgreuSua72SXOjJK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hgreuSua72SXOjJK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hgreuSua72SXOjJK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hgreuSua72SXOjJK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hgreuSua72SXOjJK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hgreuSua72SXOjJK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hgreuSua72SXOjJK .cluster text{fill:#333;}#mermaid-svg-hgreuSua72SXOjJK .cluster span{color:#333;}#mermaid-svg-hgreuSua72SXOjJK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hgreuSua72SXOjJK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hgreuSua72SXOjJK rect.text{fill:none;stroke-width:0;}#mermaid-svg-hgreuSua72SXOjJK .icon-shape,#mermaid-svg-hgreuSua72SXOjJK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hgreuSua72SXOjJK .icon-shape p,#mermaid-svg-hgreuSua72SXOjJK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hgreuSua72SXOjJK .icon-shape .label rect,#mermaid-svg-hgreuSua72SXOjJK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hgreuSua72SXOjJK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hgreuSua72SXOjJK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hgreuSua72SXOjJK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-hgreuSua72SXOjJK .client>*{fill:#e8f1ff!important;stroke:#2563eb!important;color:#172554!important;}#mermaid-svg-hgreuSua72SXOjJK .client span{fill:#e8f1ff!important;stroke:#2563eb!important;color:#172554!important;}#mermaid-svg-hgreuSua72SXOjJK .client tspan{fill:#172554!important;}#mermaid-svg-hgreuSua72SXOjJK .network>*{fill:#fff7ed!important;stroke:#ea580c!important;color:#7c2d12!important;}#mermaid-svg-hgreuSua72SXOjJK .network span{fill:#fff7ed!important;stroke:#ea580c!important;color:#7c2d12!important;}#mermaid-svg-hgreuSua72SXOjJK .network tspan{fill:#7c2d12!important;}#mermaid-svg-hgreuSua72SXOjJK .server>*{fill:#ecfdf5!important;stroke:#059669!important;color:#064e3b!important;}#mermaid-svg-hgreuSua72SXOjJK .server span{fill:#ecfdf5!important;stroke:#059669!important;color:#064e3b!important;}#mermaid-svg-hgreuSua72SXOjJK .server tspan{fill:#064e3b!important;} 是

解析 URL
本地缓存可用?
使用缓存响应
DNS 解析域名
确定路由与下一跳
建立 TCP 或 QUIC 连接
TLS 握手与证书校验
发送 HTTP 请求
CDN / 负载均衡 / 网关
应用处理并返回响应
解析、渲染与加载子资源

排障的关键是把"页面慢"还原成各阶段耗时:DNS 慢、建连慢、TLS 慢、首字节慢,还是内容下载或浏览器渲染慢。不同阶段需要完全不同的证据。

2. 浏览器如何解析 URL

URL 中的各部分承担不同职责:

text 复制代码
https://www.example.com:443/products?id=42#reviews
  |             |       |       |      |     |
协议          主机名   端口     路径   查询   片段
  • https 决定默认端口、连接安全策略和可用协议;
  • 主机名用于 DNS 解析,并参与 TLS 证书校验和 HTTP 虚拟主机路由;
  • 端口未显式给出时,HTTPS 默认使用 443;
  • 路径与查询参数会发送给服务端;
  • #reviews 片段通常只供浏览器定位页面内容,不会出现在 HTTP 请求中。

浏览器还可能先检查 HSTS,强制把 HTTP 升级为 HTTPS;也可能命中 Service Worker、内存缓存或磁盘缓存,从而不发起完整网络请求。分析问题时,应明确是首次冷访问还是已有缓存和连接的热访问。

3. DNS 如何把域名变成 IP

应用通常把查询交给系统配置的递归解析器。递归解析器若没有缓存,会沿 DNS 层次查询根服务器、顶级域服务器和权威服务器。
example.com 权威 DNS .com DNS 根 DNS 递归解析器 浏览器 / 操作系统 example.com 权威 DNS .com DNS 根 DNS 递归解析器 浏览器 / 操作系统 #mermaid-svg-nRouhwI7exg0aNag{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nRouhwI7exg0aNag .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nRouhwI7exg0aNag .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nRouhwI7exg0aNag .error-icon{fill:#552222;}#mermaid-svg-nRouhwI7exg0aNag .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nRouhwI7exg0aNag .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nRouhwI7exg0aNag .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nRouhwI7exg0aNag .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nRouhwI7exg0aNag .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nRouhwI7exg0aNag .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nRouhwI7exg0aNag .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nRouhwI7exg0aNag .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nRouhwI7exg0aNag .marker.cross{stroke:#333333;}#mermaid-svg-nRouhwI7exg0aNag svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nRouhwI7exg0aNag p{margin:0;}#mermaid-svg-nRouhwI7exg0aNag .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nRouhwI7exg0aNag text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-nRouhwI7exg0aNag .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-nRouhwI7exg0aNag .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-nRouhwI7exg0aNag .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-nRouhwI7exg0aNag .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-nRouhwI7exg0aNag #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-nRouhwI7exg0aNag .sequenceNumber{fill:white;}#mermaid-svg-nRouhwI7exg0aNag #sequencenumber{fill:#333;}#mermaid-svg-nRouhwI7exg0aNag #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-nRouhwI7exg0aNag .messageText{fill:#333;stroke:none;}#mermaid-svg-nRouhwI7exg0aNag .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nRouhwI7exg0aNag .labelText,#mermaid-svg-nRouhwI7exg0aNag .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-nRouhwI7exg0aNag .loopText,#mermaid-svg-nRouhwI7exg0aNag .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-nRouhwI7exg0aNag .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-nRouhwI7exg0aNag .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-nRouhwI7exg0aNag .noteText,#mermaid-svg-nRouhwI7exg0aNag .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-nRouhwI7exg0aNag .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nRouhwI7exg0aNag .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nRouhwI7exg0aNag .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-nRouhwI7exg0aNag .actorPopupMenu{position:absolute;}#mermaid-svg-nRouhwI7exg0aNag .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-nRouhwI7exg0aNag .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-nRouhwI7exg0aNag .actor-man circle,#mermaid-svg-nRouhwI7exg0aNag line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-nRouhwI7exg0aNag :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt递归解析器缓存命中缓存未命中 查询 www.example.com A / AAAA1返回缓存记录2查询 www.example.com3返回 .com 服务器地址4查询 www.example.com5返回权威服务器地址6查询 www.example.com7返回 A / AAAA / CNAME8返回结果与 TTL9

根服务器不会直接替所有域名回答最终地址,而是提供下一层委派信息。递归解析器代替客户端完成后续查询,并按照 TTL 缓存结果。

常见记录类型

类型 含义 常见用途
A 域名对应 IPv4 地址 IPv4 服务入口
AAAA 域名对应 IPv6 地址 IPv6 服务入口
CNAME 当前名称指向另一个名称 CDN、平台托管
MX 邮件服务器与优先级 邮件投递
TXT 任意文本信息 域名验证、SPF、DKIM
NS 域的权威 DNS 服务器 DNS 委派

CNAME 会增加名称解析步骤,但中间结果同样可以缓存。CDN 常借助 CNAME 将域名引导到其调度系统,再根据客户端位置、运营商和节点健康度返回合适地址。

TTL 与发布变更

TTL 决定缓存记录可以使用多久。把解析切到新 IP 后,旧记录不会在全球同时消失。合理流程通常是提前降低 TTL,等待旧 TTL 覆盖的缓存过期,再实施切换,最后恢复 TTL。

TTL 也不是绝对传播时间。浏览器、操作系统、递归解析器和应用各有缓存策略,部分实现可能设置最小或最大缓存时间。迁移期间应让旧入口继续提供服务,避免把 DNS 当成瞬时开关。

DNS 排查命令

bash 复制代码
dig www.example.com A
dig www.example.com AAAA
dig +trace www.example.com
nslookup www.example.com

重点检查返回码、记录链、TTL、查询服务器和耗时。NXDOMAIN 表示名称不存在,SERVFAIL 常与上游失败、DNSSEC 校验或权威服务异常有关。企业网络中的分流 DNS 还可能让内外网得到不同结果。

4. 得到 IP 后,数据包如何离开主机

主机根据路由表选择出口。如果目标 IP 与本机在同一子网,就直接寻找目标主机的链路层地址;否则将数据交给默认网关。
#mermaid-svg-x6NsDE9Gt0GZ9kws{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x6NsDE9Gt0GZ9kws .error-icon{fill:#552222;}#mermaid-svg-x6NsDE9Gt0GZ9kws .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x6NsDE9Gt0GZ9kws .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .marker.cross{stroke:#333333;}#mermaid-svg-x6NsDE9Gt0GZ9kws svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x6NsDE9Gt0GZ9kws p{margin:0;}#mermaid-svg-x6NsDE9Gt0GZ9kws .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster-label text{fill:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster-label span{color:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster-label span p{background-color:transparent;}#mermaid-svg-x6NsDE9Gt0GZ9kws .label text,#mermaid-svg-x6NsDE9Gt0GZ9kws span{fill:#333;color:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .node rect,#mermaid-svg-x6NsDE9Gt0GZ9kws .node circle,#mermaid-svg-x6NsDE9Gt0GZ9kws .node ellipse,#mermaid-svg-x6NsDE9Gt0GZ9kws .node polygon,#mermaid-svg-x6NsDE9Gt0GZ9kws .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .rough-node .label text,#mermaid-svg-x6NsDE9Gt0GZ9kws .node .label text,#mermaid-svg-x6NsDE9Gt0GZ9kws .image-shape .label,#mermaid-svg-x6NsDE9Gt0GZ9kws .icon-shape .label{text-anchor:middle;}#mermaid-svg-x6NsDE9Gt0GZ9kws .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .rough-node .label,#mermaid-svg-x6NsDE9Gt0GZ9kws .node .label,#mermaid-svg-x6NsDE9Gt0GZ9kws .image-shape .label,#mermaid-svg-x6NsDE9Gt0GZ9kws .icon-shape .label{text-align:center;}#mermaid-svg-x6NsDE9Gt0GZ9kws .node.clickable{cursor:pointer;}#mermaid-svg-x6NsDE9Gt0GZ9kws .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .arrowheadPath{fill:#333333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x6NsDE9Gt0GZ9kws .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x6NsDE9Gt0GZ9kws .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x6NsDE9Gt0GZ9kws .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster text{fill:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws .cluster span{color:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x6NsDE9Gt0GZ9kws .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x6NsDE9Gt0GZ9kws rect.text{fill:none;stroke-width:0;}#mermaid-svg-x6NsDE9Gt0GZ9kws .icon-shape,#mermaid-svg-x6NsDE9Gt0GZ9kws .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x6NsDE9Gt0GZ9kws .icon-shape p,#mermaid-svg-x6NsDE9Gt0GZ9kws .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x6NsDE9Gt0GZ9kws .icon-shape .label rect,#mermaid-svg-x6NsDE9Gt0GZ9kws .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x6NsDE9Gt0GZ9kws .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x6NsDE9Gt0GZ9kws .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x6NsDE9Gt0GZ9kws :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

得到目标 IP
查询本机路由表
目标是否同一子网?
查询目标 IP 的 MAC
选择默认网关
查询网关 IP 的 MAC
封装以太网帧
交给下一跳

IPv4 通常通过 ARP 将局域网内的 IP 映射为 MAC 地址;IPv6 使用邻居发现协议 NDP。ARP 只解决当前广播域中的下一跳寻址,不会查询远端服务器的 MAC。

bash 复制代码
ip route get 203.0.113.10
ip neigh
arp -a

Windows 可使用 route printGet-NetRouteGet-NetNeighbor。若同网段地址不可达,应检查 VLAN、子网掩码、邻居表和交换网络;若跨网段不可达,则继续检查默认路由和中间路径。

5. 路由器如何转发数据包

每台路由器根据目标 IP 查询路由表,采用最长前缀匹配选择下一跳,并递减 TTL 或 Hop Limit。路由器通常不知道完整的端到端路径,只负责把包交给自己认为合适的下一跳。

text 复制代码
客户端 -> 家庭/企业网关 -> 运营商网络 -> 骨干网 -> 目标网络 -> 服务入口

IPv4 私网客户端常通过 NAT 访问公网。网关会把私网源地址和端口改写为公网地址与端口,并维护映射状态。NAT 不是防火墙的同义词,但有状态 NAT 通常会阻止没有对应映射的外部连接直接进入。
服务端 203.0.113.10:443 NAT 网关 198.51.100.8 客户端 192.168.1.20:51500 服务端 203.0.113.10:443 NAT 网关 198.51.100.8 客户端 192.168.1.20:51500 #mermaid-svg-tTiwGRIARGdjF66u{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tTiwGRIARGdjF66u .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tTiwGRIARGdjF66u .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tTiwGRIARGdjF66u .error-icon{fill:#552222;}#mermaid-svg-tTiwGRIARGdjF66u .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tTiwGRIARGdjF66u .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tTiwGRIARGdjF66u .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tTiwGRIARGdjF66u .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tTiwGRIARGdjF66u .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tTiwGRIARGdjF66u .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tTiwGRIARGdjF66u .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tTiwGRIARGdjF66u .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tTiwGRIARGdjF66u .marker.cross{stroke:#333333;}#mermaid-svg-tTiwGRIARGdjF66u svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tTiwGRIARGdjF66u p{margin:0;}#mermaid-svg-tTiwGRIARGdjF66u .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTiwGRIARGdjF66u text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-tTiwGRIARGdjF66u .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tTiwGRIARGdjF66u .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-tTiwGRIARGdjF66u .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-tTiwGRIARGdjF66u .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-tTiwGRIARGdjF66u #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-tTiwGRIARGdjF66u .sequenceNumber{fill:white;}#mermaid-svg-tTiwGRIARGdjF66u #sequencenumber{fill:#333;}#mermaid-svg-tTiwGRIARGdjF66u #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-tTiwGRIARGdjF66u .messageText{fill:#333;stroke:none;}#mermaid-svg-tTiwGRIARGdjF66u .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTiwGRIARGdjF66u .labelText,#mermaid-svg-tTiwGRIARGdjF66u .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-tTiwGRIARGdjF66u .loopText,#mermaid-svg-tTiwGRIARGdjF66u .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-tTiwGRIARGdjF66u .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tTiwGRIARGdjF66u .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-tTiwGRIARGdjF66u .noteText,#mermaid-svg-tTiwGRIARGdjF66u .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-tTiwGRIARGdjF66u .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTiwGRIARGdjF66u .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTiwGRIARGdjF66u .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTiwGRIARGdjF66u .actorPopupMenu{position:absolute;}#mermaid-svg-tTiwGRIARGdjF66u .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-tTiwGRIARGdjF66u .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTiwGRIARGdjF66u .actor-man circle,#mermaid-svg-tTiwGRIARGdjF66u line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-tTiwGRIARGdjF66u :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} src=192.168.1.20:51500改写 src=198.51.100.8:62001dst=198.51.100.8:62001还原 dst=192.168.1.20:51500

traceroutetracert 利用逐步增加 TTL 观察部分中间跳,但看不到某一跳响应并不等于该路由器不转发业务流量。设备可能限制或丢弃诊断报文,去程和回程也可能走不同路径。

6. HTTPS 连接建立:TCP 与 TLS

传统 HTTPS 通常先建立 TCP 连接,再执行 TLS 握手。TLS 1.3 的一次完整握手可简化表示为:
HTTPS 服务端 客户端 HTTPS 服务端 客户端 #mermaid-svg-Rj0BOrvcwFfe9Rna{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Rj0BOrvcwFfe9Rna .error-icon{fill:#552222;}#mermaid-svg-Rj0BOrvcwFfe9Rna .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Rj0BOrvcwFfe9Rna .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Rj0BOrvcwFfe9Rna .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Rj0BOrvcwFfe9Rna .marker.cross{stroke:#333333;}#mermaid-svg-Rj0BOrvcwFfe9Rna svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Rj0BOrvcwFfe9Rna p{margin:0;}#mermaid-svg-Rj0BOrvcwFfe9Rna .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Rj0BOrvcwFfe9Rna text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Rj0BOrvcwFfe9Rna .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Rj0BOrvcwFfe9Rna .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Rj0BOrvcwFfe9Rna #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Rj0BOrvcwFfe9Rna .sequenceNumber{fill:white;}#mermaid-svg-Rj0BOrvcwFfe9Rna #sequencenumber{fill:#333;}#mermaid-svg-Rj0BOrvcwFfe9Rna #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Rj0BOrvcwFfe9Rna .messageText{fill:#333;stroke:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Rj0BOrvcwFfe9Rna .labelText,#mermaid-svg-Rj0BOrvcwFfe9Rna .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .loopText,#mermaid-svg-Rj0BOrvcwFfe9Rna .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Rj0BOrvcwFfe9Rna .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Rj0BOrvcwFfe9Rna .noteText,#mermaid-svg-Rj0BOrvcwFfe9Rna .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Rj0BOrvcwFfe9Rna .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Rj0BOrvcwFfe9Rna .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Rj0BOrvcwFfe9Rna .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Rj0BOrvcwFfe9Rna .actorPopupMenu{position:absolute;}#mermaid-svg-Rj0BOrvcwFfe9Rna .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Rj0BOrvcwFfe9Rna .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Rj0BOrvcwFfe9Rna .actor-man circle,#mermaid-svg-Rj0BOrvcwFfe9Rna line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Rj0BOrvcwFfe9Rna :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 验证证书链与主机名导出会话密钥 TCP SYN1SYN + ACK2ACK3ClientHello版本、密码套件、SNI、密钥份额、ALPN4ServerHello选定参数、证书、Finished5Finished + HTTP 请求6加密的 HTTP 响应7

实际报文可能因分片、会话恢复、0-RTT、客户端证书和中间设备而不同。TLS 1.3 相比旧版本减少了握手往返次数,但首次访问仍会受到网络 RTT 影响。

SNI 与 ALPN

  • SNI:客户端在握手中告知希望访问的主机名,使同一 IP 上的服务器可以选择正确证书;
  • ALPN :客户端与服务器协商上层协议,例如 h2http/1.1
  • ECH:在支持的环境中可进一步保护 ClientHello 中的敏感信息,但部署依赖客户端、DNS 和服务端共同支持。

浏览器如何验证证书

客户端至少需要确认:

  1. 当前时间在证书有效期内;
  2. 访问的主机名与证书 SAN 匹配;
  3. 证书链最终连接到受信任根证书;
  4. 签名、密钥用途与算法满足安全策略;
  5. 撤销状态在客户端策略要求下可接受。

服务器通常发送站点证书和必要的中间证书,不发送根证书。客户端使用本地信任库中的根证书完成验证。漏配中间证书可能导致"部分设备正常、部分设备失败"。

bash 复制代码
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts
curl -v https://www.example.com/

使用 IP 直连测试 HTTPS 时仍应保留正确的主机名,否则 SNI、证书校验和虚拟主机路由都可能改变结果。例如 curl --resolve 可以临时指定域名到 IP 的映射,而不破坏主机名语义。

7. HTTP 请求中包含什么

完成安全连接后,浏览器发送 HTTP 请求。HTTP/1.1 的文本形式便于理解:

http 复制代码
GET /products?id=42 HTTP/1.1
Host: www.example.com
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, br
Cookie: session=...
User-Agent: ...

服务端返回状态行、响应头和响应体:

http 复制代码
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: br
Cache-Control: public, max-age=300
Content-Length: 8421

<!doctype html>...

HTTPS 加密 HTTP 的头部和正文,但不会隐藏通信双方 IP、数据量、时序等元数据。传统 TLS 中的 SNI 也可能可见。

8. HTTP/1.1、HTTP/2 与 HTTP/3

特性 HTTP/1.1 HTTP/2 HTTP/3
底层传输 TCP TCP QUIC / UDP
多路复用 通常依赖多连接 单连接多流 单连接多流
头部压缩 无内建压缩 HPACK QPACK
丢包影响 当前连接 TCP 层影响连接内所有流 通常限制在相关 QUIC 流
连接迁移 不支持 不支持 支持连接 ID 驱动的迁移

HTTP/2 解决了 HTTP/1.1 应用层队头阻塞和大量并发连接问题,但底层 TCP 丢包仍可能暂停同一连接上的所有流。HTTP/3 将传输能力构建在 QUIC 上,使不同流之间更独立,并能整合传输与 TLS 握手。

协议版本不是越新就一定越快。握手复用率、丢包、服务器实现、UDP 可达性和负载均衡能力都会影响结果。生产环境应基于真实用户指标比较。

9. 请求如何经过 CDN、负载均衡与网关

公网 IP 往往不是业务应用所在主机的地址。请求可能经过多层基础设施:
#mermaid-svg-cVNp8PQ55KewfAQL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cVNp8PQ55KewfAQL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cVNp8PQ55KewfAQL .error-icon{fill:#552222;}#mermaid-svg-cVNp8PQ55KewfAQL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cVNp8PQ55KewfAQL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cVNp8PQ55KewfAQL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cVNp8PQ55KewfAQL .marker.cross{stroke:#333333;}#mermaid-svg-cVNp8PQ55KewfAQL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cVNp8PQ55KewfAQL p{margin:0;}#mermaid-svg-cVNp8PQ55KewfAQL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cVNp8PQ55KewfAQL .cluster-label text{fill:#333;}#mermaid-svg-cVNp8PQ55KewfAQL .cluster-label span{color:#333;}#mermaid-svg-cVNp8PQ55KewfAQL .cluster-label span p{background-color:transparent;}#mermaid-svg-cVNp8PQ55KewfAQL .label text,#mermaid-svg-cVNp8PQ55KewfAQL span{fill:#333;color:#333;}#mermaid-svg-cVNp8PQ55KewfAQL .node rect,#mermaid-svg-cVNp8PQ55KewfAQL .node circle,#mermaid-svg-cVNp8PQ55KewfAQL .node ellipse,#mermaid-svg-cVNp8PQ55KewfAQL .node polygon,#mermaid-svg-cVNp8PQ55KewfAQL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cVNp8PQ55KewfAQL .rough-node .label text,#mermaid-svg-cVNp8PQ55KewfAQL .node .label text,#mermaid-svg-cVNp8PQ55KewfAQL .image-shape .label,#mermaid-svg-cVNp8PQ55KewfAQL .icon-shape .label{text-anchor:middle;}#mermaid-svg-cVNp8PQ55KewfAQL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cVNp8PQ55KewfAQL .rough-node .label,#mermaid-svg-cVNp8PQ55KewfAQL .node .label,#mermaid-svg-cVNp8PQ55KewfAQL .image-shape .label,#mermaid-svg-cVNp8PQ55KewfAQL .icon-shape .label{text-align:center;}#mermaid-svg-cVNp8PQ55KewfAQL .node.clickable{cursor:pointer;}#mermaid-svg-cVNp8PQ55KewfAQL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cVNp8PQ55KewfAQL .arrowheadPath{fill:#333333;}#mermaid-svg-cVNp8PQ55KewfAQL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cVNp8PQ55KewfAQL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cVNp8PQ55KewfAQL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cVNp8PQ55KewfAQL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cVNp8PQ55KewfAQL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cVNp8PQ55KewfAQL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cVNp8PQ55KewfAQL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cVNp8PQ55KewfAQL .cluster text{fill:#333;}#mermaid-svg-cVNp8PQ55KewfAQL .cluster span{color:#333;}#mermaid-svg-cVNp8PQ55KewfAQL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cVNp8PQ55KewfAQL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cVNp8PQ55KewfAQL rect.text{fill:none;stroke-width:0;}#mermaid-svg-cVNp8PQ55KewfAQL .icon-shape,#mermaid-svg-cVNp8PQ55KewfAQL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cVNp8PQ55KewfAQL .icon-shape p,#mermaid-svg-cVNp8PQ55KewfAQL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cVNp8PQ55KewfAQL .icon-shape .label rect,#mermaid-svg-cVNp8PQ55KewfAQL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cVNp8PQ55KewfAQL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cVNp8PQ55KewfAQL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cVNp8PQ55KewfAQL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 缓存命中
用户浏览器
CDN 边缘节点
WAF / DDoS 防护
四层或七层负载均衡
API 网关 / 反向代理
应用实例 A
应用实例 B
数据库 / 缓存

  • CDN 在边缘缓存静态或可缓存内容,减少回源距离和源站压力;
  • WAF 根据规则识别恶意请求;
  • 四层负载均衡主要依据 IP 和端口转发,七层负载均衡可以理解 HTTP 主机名、路径和头部;
  • API 网关可负责认证、限流、路由、观测和协议转换;
  • 应用继续访问缓存、数据库或其他服务。

每一层都可能终止并重新建立连接。因此客户端看到的 TCP RTT 可能只到 CDN,客户端证书对应的也可能是 CDN;回源连接则是另一条独立链路。排障时必须明确指标属于哪一段。

10. HTTP 缓存如何决定是否访问服务端

缓存既能降低延迟,也会让"为什么仍看到旧内容"变得复杂。浏览器和共享缓存主要依据响应头决定行为。
#mermaid-svg-k0QOV65weQG01uLY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-k0QOV65weQG01uLY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-k0QOV65weQG01uLY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-k0QOV65weQG01uLY .error-icon{fill:#552222;}#mermaid-svg-k0QOV65weQG01uLY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-k0QOV65weQG01uLY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-k0QOV65weQG01uLY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-k0QOV65weQG01uLY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-k0QOV65weQG01uLY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-k0QOV65weQG01uLY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-k0QOV65weQG01uLY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-k0QOV65weQG01uLY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-k0QOV65weQG01uLY .marker.cross{stroke:#333333;}#mermaid-svg-k0QOV65weQG01uLY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-k0QOV65weQG01uLY p{margin:0;}#mermaid-svg-k0QOV65weQG01uLY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-k0QOV65weQG01uLY .cluster-label text{fill:#333;}#mermaid-svg-k0QOV65weQG01uLY .cluster-label span{color:#333;}#mermaid-svg-k0QOV65weQG01uLY .cluster-label span p{background-color:transparent;}#mermaid-svg-k0QOV65weQG01uLY .label text,#mermaid-svg-k0QOV65weQG01uLY span{fill:#333;color:#333;}#mermaid-svg-k0QOV65weQG01uLY .node rect,#mermaid-svg-k0QOV65weQG01uLY .node circle,#mermaid-svg-k0QOV65weQG01uLY .node ellipse,#mermaid-svg-k0QOV65weQG01uLY .node polygon,#mermaid-svg-k0QOV65weQG01uLY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-k0QOV65weQG01uLY .rough-node .label text,#mermaid-svg-k0QOV65weQG01uLY .node .label text,#mermaid-svg-k0QOV65weQG01uLY .image-shape .label,#mermaid-svg-k0QOV65weQG01uLY .icon-shape .label{text-anchor:middle;}#mermaid-svg-k0QOV65weQG01uLY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-k0QOV65weQG01uLY .rough-node .label,#mermaid-svg-k0QOV65weQG01uLY .node .label,#mermaid-svg-k0QOV65weQG01uLY .image-shape .label,#mermaid-svg-k0QOV65weQG01uLY .icon-shape .label{text-align:center;}#mermaid-svg-k0QOV65weQG01uLY .node.clickable{cursor:pointer;}#mermaid-svg-k0QOV65weQG01uLY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-k0QOV65weQG01uLY .arrowheadPath{fill:#333333;}#mermaid-svg-k0QOV65weQG01uLY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-k0QOV65weQG01uLY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-k0QOV65weQG01uLY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k0QOV65weQG01uLY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-k0QOV65weQG01uLY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k0QOV65weQG01uLY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-k0QOV65weQG01uLY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-k0QOV65weQG01uLY .cluster text{fill:#333;}#mermaid-svg-k0QOV65weQG01uLY .cluster span{color:#333;}#mermaid-svg-k0QOV65weQG01uLY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-k0QOV65weQG01uLY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-k0QOV65weQG01uLY rect.text{fill:none;stroke-width:0;}#mermaid-svg-k0QOV65weQG01uLY .icon-shape,#mermaid-svg-k0QOV65weQG01uLY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k0QOV65weQG01uLY .icon-shape p,#mermaid-svg-k0QOV65weQG01uLY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-k0QOV65weQG01uLY .icon-shape .label rect,#mermaid-svg-k0QOV65weQG01uLY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k0QOV65weQG01uLY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-k0QOV65weQG01uLY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-k0QOV65weQG01uLY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否





准备请求资源
本地是否有缓存?
发送普通请求
缓存是否仍新鲜?
直接使用缓存
携带 If-None-Match

或 If-Modified-Since
资源是否变化?
304 Not Modified

复用缓存正文
200 OK

返回新正文

常见指令包括:

  • Cache-Control: max-age=300:响应在 300 秒内可视为新鲜;
  • no-cache:可以存储,但使用前必须重新验证;
  • no-store:不应存储响应;
  • private:只允许私有缓存保存;
  • ETag:资源版本标识,可配合 If-None-Match 验证;
  • Vary:说明缓存键还受哪些请求头影响,如 Accept-Encoding

带哈希的静态资源文件名适合长缓存;HTML 入口通常使用短缓存或协商缓存,以便及时引用新版本资源。发布系统应保证资源版本和缓存策略协同,而不是靠用户手动清缓存。

11. 重定向、Cookie 与同源边界

服务端可能通过 301302307308 让浏览器访问新地址。每次跨主机重定向都可能引入新的 DNS、连接和 TLS 成本。重定向链过长既影响性能,也增加配置错误风险。

Cookie 会根据 Domain、Path、Secure、HttpOnly 和 SameSite 等属性决定是否随请求发送。Cookie 太大或数量太多会增加每次请求头开销;会话 Cookie 还涉及隐私与安全,不能写入日志或前端可访问位置。

同源由协议、主机和端口共同决定。浏览器的同源策略限制脚本读取跨源响应,CORS 是服务端显式放宽读取权限的机制。CORS 错误通常是浏览器安全策略导致,并不表示请求一定没有到达服务端。

12. 如何测量请求慢在哪一段

curl 可以输出关键时间点:

bash 复制代码
curl -sS -o /dev/null \
  -w 'dns=%{time_namelookup}\nconnect=%{time_connect}\ntls=%{time_appconnect}\nfirst_byte=%{time_starttransfer}\ntotal=%{time_total}\n' \
  https://www.example.com/

这些指标大致表示:

指标 含义 高耗时常见方向
time_namelookup DNS 完成时间 解析器慢、丢包、权威 DNS 异常
time_connect TCP 建连完成时间 网络 RTT、丢包、防火墙、监听队列
time_appconnect TLS 完成时间 RTT、证书链、TLS 计算或代理
time_starttransfer 收到首字节时间 网关排队、应用和下游处理
time_total 完整传输时间 响应体大小、带宽、丢包、客户端处理

各值是从请求开始累计的时间点,不应直接把 time_starttransfer 全部归因于服务端。要得到某阶段耗时,需要结合前一个时间点计算差值。

浏览器开发者工具的 Network 面板还能显示排队、连接复用、请求发送、等待首字节和内容下载。服务端应使用统一请求 ID、分布式追踪和反向代理计时,把客户端瀑布图与内部调用链对齐。

13. 一套分层排障流程

#mermaid-svg-pxAe2EeyRn7vqNTs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pxAe2EeyRn7vqNTs .error-icon{fill:#552222;}#mermaid-svg-pxAe2EeyRn7vqNTs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pxAe2EeyRn7vqNTs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pxAe2EeyRn7vqNTs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pxAe2EeyRn7vqNTs .marker.cross{stroke:#333333;}#mermaid-svg-pxAe2EeyRn7vqNTs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pxAe2EeyRn7vqNTs p{margin:0;}#mermaid-svg-pxAe2EeyRn7vqNTs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster-label text{fill:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster-label span{color:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster-label span p{background-color:transparent;}#mermaid-svg-pxAe2EeyRn7vqNTs .label text,#mermaid-svg-pxAe2EeyRn7vqNTs span{fill:#333;color:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs .node rect,#mermaid-svg-pxAe2EeyRn7vqNTs .node circle,#mermaid-svg-pxAe2EeyRn7vqNTs .node ellipse,#mermaid-svg-pxAe2EeyRn7vqNTs .node polygon,#mermaid-svg-pxAe2EeyRn7vqNTs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pxAe2EeyRn7vqNTs .rough-node .label text,#mermaid-svg-pxAe2EeyRn7vqNTs .node .label text,#mermaid-svg-pxAe2EeyRn7vqNTs .image-shape .label,#mermaid-svg-pxAe2EeyRn7vqNTs .icon-shape .label{text-anchor:middle;}#mermaid-svg-pxAe2EeyRn7vqNTs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pxAe2EeyRn7vqNTs .rough-node .label,#mermaid-svg-pxAe2EeyRn7vqNTs .node .label,#mermaid-svg-pxAe2EeyRn7vqNTs .image-shape .label,#mermaid-svg-pxAe2EeyRn7vqNTs .icon-shape .label{text-align:center;}#mermaid-svg-pxAe2EeyRn7vqNTs .node.clickable{cursor:pointer;}#mermaid-svg-pxAe2EeyRn7vqNTs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pxAe2EeyRn7vqNTs .arrowheadPath{fill:#333333;}#mermaid-svg-pxAe2EeyRn7vqNTs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pxAe2EeyRn7vqNTs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pxAe2EeyRn7vqNTs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pxAe2EeyRn7vqNTs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pxAe2EeyRn7vqNTs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pxAe2EeyRn7vqNTs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster text{fill:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs .cluster span{color:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pxAe2EeyRn7vqNTs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pxAe2EeyRn7vqNTs rect.text{fill:none;stroke-width:0;}#mermaid-svg-pxAe2EeyRn7vqNTs .icon-shape,#mermaid-svg-pxAe2EeyRn7vqNTs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pxAe2EeyRn7vqNTs .icon-shape p,#mermaid-svg-pxAe2EeyRn7vqNTs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pxAe2EeyRn7vqNTs .icon-shape .label rect,#mermaid-svg-pxAe2EeyRn7vqNTs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pxAe2EeyRn7vqNTs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pxAe2EeyRn7vqNTs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pxAe2EeyRn7vqNTs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否









访问失败或延迟高
域名能否正确解析?
检查 DNS 返回码、记录链、TTL
目标端口能否建连?
检查路由、ACL、防火墙、监听状态
TLS 是否成功?
检查 SNI、证书链、时间、协议套件
HTTP 状态与首字节正常?
检查 CDN、网关、应用与下游
下载或渲染是否慢?
检查缓存、压缩、资源大小、前端性能
请求链路正常

建议按以下顺序收集证据:

  1. 记录准确的时间、客户端网络、URL、状态码和请求 ID;
  2. 查询 DNS,并确认实际连接的 IP;
  3. 测试端口连通性和路由;
  4. 检查 TLS 证书链、SNI 与协商协议;
  5. 分解 DNS、连接、TLS、首字节和下载耗时;
  6. 结合 CDN、负载均衡、网关、应用和下游指标定位具体一段。

不要一开始就清理全部缓存或重启服务,这会破坏现场并掩盖根因。先保留失败样本、时间窗口和链路证据。

14. 常见故障如何解释

DNS 正常,但浏览器提示连接超时

DNS 只证明得到了地址。目标端口可能未监听,路由或防火墙可能丢包,IPv6 地址也可能已发布但路径不可用。应分别测试 A 与 AAAA 结果对应的连接。

IP 直连正常,域名访问失败

域名访问还涉及 SNI、Host 头、证书校验、CDN 和虚拟主机路由。单纯访问 IP 可能命中默认站点,不能证明完整链路正常。使用保留主机名语义的方式测试更可靠。

返回 502、503 或 504

  • 502 Bad Gateway:代理收到无效上游响应或上游连接异常;
  • 503 Service Unavailable:服务不可用、过载或正在维护;
  • 504 Gateway Timeout:网关等待上游超时。

状态码只能指出报告问题的层次,不能单独确定根因。仍需查看生成该状态码的设备日志和上游指标。

首次访问慢,刷新后很快

首次访问可能包含 DNS、TCP、TLS、缓存未命中和应用冷启动;刷新则能复用连接、TLS 会话、DNS 与内容缓存。应分别测量冷启动和热访问,而不是用后者掩盖首次体验。

15. 常见误区

  1. DNS 使用 TCP,所以一定可靠但慢。 传统 DNS 常先使用 UDP,在响应截断、区域传送等场景使用 TCP;现代 DNS 还可能运行在 TLS、HTTPS 或 QUIC 上。
  2. Ping 不通表示网站不可用。 ICMP 可能被限制,而 TCP 443 仍正常;反过来,Ping 通也不代表应用可用。
  3. HTTPS 会隐藏目标 IP。 IP 路由仍需要目标地址,HTTPS 主要保护 HTTP 内容与身份认证。
  4. 证书有效期正常就一定可信。 还要检查主机名、证书链、用途、算法和信任根。
  5. HTTP 304 是错误。 它表示资源未修改,客户端应复用本地缓存正文。
  6. CDN 命中意味着源站完全没参与。 缓存刷新、鉴权、动态内容和回源验证都可能继续访问源站。

16. 总结

从 URL 到页面返回是一条跨层链路:URL 决定访问语义,DNS 把名称映射为地址,路由与邻居发现将数据送往下一跳,TCP 或 QUIC 建立传输通道,TLS 验证身份并协商加密,HTTP 表达请求与响应,CDN、负载均衡和网关再把流量送到应用。

真正有效的排障不是背诵步骤,而是给每个阶段建立可验证的问题:解析到了什么地址、连接到了哪一段、证书为何可信、首字节时间花在哪里、缓存由谁命中。按层收集证据并对齐时间线,才能把笼统的"网络慢"收敛为可以处理的具体故障。

相关推荐
ttod_qzstudio2 小时前
Java 常用语法极简通关(五):类与对象——字段、方法、构造器、this 与 static
java·开发语言·python
DevUI团队2 小时前
从“即兴创作”到“规格先行”,华为云码道(CodeArts)代码智能体持续深耕企业级规范驱动开发能力
前端·人工智能·后端
萧瑟余晖3 小时前
Java深入解析篇十七之Spring Security
java·开发语言·spring
weixin_431600443 小时前
NestJS 入门(3):Guard 如何挡住未登录请求?
前端·后端·学习·nest.js
IT_陈寒4 小时前
JavaScript类型转换把我坑惨了,这破玩意真该早点搞明白
前端·人工智能·后端
白狐_7984 小时前
408计算机网络第3章:PPP协议——帧格式、LCP/NCP、状态机与真题精讲
网络·计算机网络·智能路由器
用户938515635074 小时前
手写一个 LLM Harness 框架:用工程化手段把大模型幻觉踩在脚下
javascript·人工智能·后端
wei_shuo5 小时前
KES 云原生部署与弹性扩展:容器化、Kubernetes编排与自动伸缩
后端
一木之林5 小时前
Python.五.(一)--1. 并发编程、异步IO与多进程
后端