在浏览器输入一个 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 print、Get-NetRoute 和 Get-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
traceroute 或 tracert 利用逐步增加 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 :客户端与服务器协商上层协议,例如
h2或http/1.1; - ECH:在支持的环境中可进一步保护 ClientHello 中的敏感信息,但部署依赖客户端、DNS 和服务端共同支持。
浏览器如何验证证书
客户端至少需要确认:
- 当前时间在证书有效期内;
- 访问的主机名与证书 SAN 匹配;
- 证书链最终连接到受信任根证书;
- 签名、密钥用途与算法满足安全策略;
- 撤销状态在客户端策略要求下可接受。
服务器通常发送站点证书和必要的中间证书,不发送根证书。客户端使用本地信任库中的根证书完成验证。漏配中间证书可能导致"部分设备正常、部分设备失败"。
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 与同源边界
服务端可能通过 301、302、307 或 308 让浏览器访问新地址。每次跨主机重定向都可能引入新的 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、网关、应用与下游
下载或渲染是否慢?
检查缓存、压缩、资源大小、前端性能
请求链路正常
建议按以下顺序收集证据:
- 记录准确的时间、客户端网络、URL、状态码和请求 ID;
- 查询 DNS,并确认实际连接的 IP;
- 测试端口连通性和路由;
- 检查 TLS 证书链、SNI 与协商协议;
- 分解 DNS、连接、TLS、首字节和下载耗时;
- 结合 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. 常见误区
- DNS 使用 TCP,所以一定可靠但慢。 传统 DNS 常先使用 UDP,在响应截断、区域传送等场景使用 TCP;现代 DNS 还可能运行在 TLS、HTTPS 或 QUIC 上。
- Ping 不通表示网站不可用。 ICMP 可能被限制,而 TCP 443 仍正常;反过来,Ping 通也不代表应用可用。
- HTTPS 会隐藏目标 IP。 IP 路由仍需要目标地址,HTTPS 主要保护 HTTP 内容与身份认证。
- 证书有效期正常就一定可信。 还要检查主机名、证书链、用途、算法和信任根。
- HTTP 304 是错误。 它表示资源未修改,客户端应复用本地缓存正文。
- CDN 命中意味着源站完全没参与。 缓存刷新、鉴权、动态内容和回源验证都可能继续访问源站。
16. 总结
从 URL 到页面返回是一条跨层链路:URL 决定访问语义,DNS 把名称映射为地址,路由与邻居发现将数据送往下一跳,TCP 或 QUIC 建立传输通道,TLS 验证身份并协商加密,HTTP 表达请求与响应,CDN、负载均衡和网关再把流量送到应用。
真正有效的排障不是背诵步骤,而是给每个阶段建立可验证的问题:解析到了什么地址、连接到了哪一段、证书为何可信、首字节时间花在哪里、缓存由谁命中。按层收集证据并对齐时间线,才能把笼统的"网络慢"收敛为可以处理的具体故障。