浏览器访问背后的秘密:从加载到关闭,数据是否会丢失?

Scroll Down

⏩ 一次浏览器访问 www.xxx.com 背后发生了什么?
—— 以及“我点了 ×,数据会不会丢?”的深度剖析

适读人群:Web 开发者、运维工程师、性能调优/安全从业者


1️⃣ 打开浏览器敲下网址:链路是如何启动的?

阶段 关键词 关键细节
解析阶段 DNS、缓存 浏览器先查本地/系统 DNS 缓存 → hosts → 浏览器 DNS 缓存 → 递归查询(可能走 DoH/DoT)。拿到 A / AAAA 记录。
连接阶段 TCP 3‑way、TLS 1.3 TCP:SYN → SYN‑ACK → ACK;若启用 QUIC/HTTP‑3 则直接 UDP 把 3 次握手+TLS 合并。
TLS:ClientHello→ServerHello→ … → Finished,现代浏览器基本启用 0‑RTT/1‑RTT。
请求阶段 HTTP/2、HPACK、首部压缩 浏览器构造 GET /,附带头(UA、Cookie、Accept‑Encoding…),优先用 HTTP/2 多路复用并发流。
服务器内部 负载均衡、反向代理、应用层 可能经历 ELB/Nginx/Sidecar,再到业务容器;中间会有 队列、限流、熔断
响应阶段 TCP 流/ QUIC 流 服务器写回状态行+头+Body;浏览器解析 HTML 发现静态资源→并发下载→渲染。
结束阶段 FIN、连接复用 HTTP/1.1的长连接或 H2/H3 的流会保持空闲等待复用;超时或浏览器关闭时发送 FIN

2️⃣ “我等得太慢点了 ×,服务器会怎么想?”

2.1 浏览器侧:取消动作

  • 显式取消:用户点击“停止加载”或关闭 Tab。
    浏览器对活跃的 TCP/QUIC 流发送 RST(或 HTTP/2 RST_STREAM)。
  • 隐式取消:超时时间到、页面卸载等;浏览器会 abort fetch,内核可能直接 close() 套接字。

2.2 网络层:信号传递

协议 取消信号 服务器感知
TCP RST 立即终止连接;内核返回 ECONNRESET,应用读/写触发异常。
HTTP/2 RST_STREAM (error‑code=0) 仅关闭对应流,复用的其他流不受影响;h2 服务器收到回调。
QUIC/HTTP‑3 STOP_SENDING / RESET_STREAM 与 h2 类似,但基于 UDP;更快释放流。

2.3 服务器侧:请求已经“进厨房”怎么办?

  1. 刚到负载均衡

    • 连接被复用,RST 直接丢弃,Nginx 可能还没把请求转给应用,成本小。
  2. 已进应用但未执行业务

    • 线程/协程池检测到 socket 断开会抛 IOException;大多数框架(Spring MVC、Express、Gin…)会捕获记录 ClientAbortException 后结束。
  3. 业务正在执行

    • CPU 正烧:图片压缩、大 SQL、RPC…
    • 同步模型:直到代码写响应时才发现对端关闭 → 计算白做了,但数据未写出,资源浪费
    • 异步/事件模型:中途可检测 connectionAborted flag 主动中止。
  4. 下游已持久化

    • 例如下单接口:一旦写入数据库/消息队列,就算用户取消,也已成功。
    • 于是就有了 支付回调、“查看订单”按钮来补偿交互的不确定性。

3️⃣ “数据丢不丢?”—— 三个不同层次的回答

角度 是否丢失? 解释
传输层 ✅ 丢 浏览器取消后,剩余报文不再发送;未到达的响应也不再接收。
应用层 ❌ 不一定 服务器可能已完整处理,持久化成功。仅“用户没看到”而已。
业务语义 需要幂等 好的接口要做到 幂等&可重试:PUT/DELETE 设计有幂等键,POST 返回可查询的 operationId

4️⃣ 工程实践:让“取消”更友好

  1. 前端

    • AbortController 取消 fetch;
    • 超时反馈:Skeleton Screen / 旋转骨架;
    • 使用 web‑worker + keep‑alive 提升体验。
  2. 网关/反代

    • 配置 proxy_request_buffering off (Nginx) 让大上传即时回源;
    • 针对 client_abort 及时丢弃后端响应。
  3. 后端

    • 设计 可中断任务:定期检查 Thread.currentThread().isInterrupted()
    • 重型计算放入 作业队列,前端轮询 jobId
    • 数据库写操作加 事务/唯一约束 保证幂等。
  4. 监控

    • 关注 499 Client Closed Request(Nginx)、444 No Response
    • 链路追踪标记 aborted=true,评估浪费。

5️⃣ 小结

  • 用户取消请求后,网络传输层面数据一定中断
  • 服务器逻辑可能仍在继续,甚至已成功写库;
  • 工程上通过 幂等、作业分离、连接检测 将“浪费”降到最低;
  • 让前端与后端都能 优雅应对取消,才是真正的端到端体验优化。